From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CE35C43334 for ; Fri, 15 Jul 2022 07:06:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231828AbiGOHGn (ORCPT ); Fri, 15 Jul 2022 03:06:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231211AbiGOHGM (ORCPT ); Fri, 15 Jul 2022 03:06:12 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 123556EE9E for ; Fri, 15 Jul 2022 00:06:07 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S3; Fri, 15 Jul 2022 15:05:55 +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 V15 01/15] ACPICA: MADT: Add LoongArch APICs support Date: Fri, 15 Jul 2022 15:05:37 +0800 Message-Id: <1657868751-30444-2-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S3 X-Coremail-Antispam: 1UD129KBjvJXoWxXrWDKF17KF4xWF4UZF4DCFg_yoW7Jry3pF Wjg343Gw4UXFWftr1aqay8A3W3Ja4rAFn7Wws3Ca43XrnrKrWUZFWvyr17GFZxJa1rtay3 ZF10v3W8Wa1xArJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkE1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j 6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUdHU DUUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen LoongArch-specific interrupt controllers (similar to APIC) are added in the next revision of ACPI Specification (current revision is 6.4), which including CORE_PIC (CPUINTC), LIO_PIC (LIOINTC), EIO_PIC (EIOINTC), HT_PIC (HTVECINTC), BIO_PIC (PCHINTC), LPC_PIC (PCHLPC) and MSI_PIC (PCHMSI). This patch add their definition. ACPI changes of LoongArch-specific interrupt controllers have already been approved in the ECRs, and will be public in the next revision of ACPI Specification. Reference: https://mantis.uefi.org/mantis/view.php?id=3D2203 Reference: https://mantis.uefi.org/mantis/view.php?id=3D2313 Above links needs login(available for ASWG), so the following link( the ECR file for adding LoongArch APICs into ACPI spec) is provided for public: https://github.com/lvjianmin-loongson/acpica/blob/master/Add%20APIC%20Struc= tures%20for%20Loongarch%20in%20MADT-rev3.pdf Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- include/acpi/actbl2.h | 127 ++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 655102b..323bdd6 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -865,7 +865,14 @@ enum acpi_madt_type { ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR =3D 14, ACPI_MADT_TYPE_GENERIC_TRANSLATOR =3D 15, ACPI_MADT_TYPE_MULTIPROC_WAKEUP =3D 16, - ACPI_MADT_TYPE_RESERVED =3D 17, /* 17 to 0x7F are reserved */ + ACPI_MADT_TYPE_CORE_PIC =3D 17, + ACPI_MADT_TYPE_LIO_PIC =3D 18, + ACPI_MADT_TYPE_HT_PIC =3D 19, + ACPI_MADT_TYPE_EIO_PIC =3D 20, + ACPI_MADT_TYPE_MSI_PIC =3D 21, + ACPI_MADT_TYPE_BIO_PIC =3D 22, + ACPI_MADT_TYPE_LPC_PIC =3D 23, + ACPI_MADT_TYPE_RESERVED =3D 24, /* 24 to 0x7F are reserved */ ACPI_MADT_TYPE_OEM_RESERVED =3D 0x80 /* 0x80 to 0xFF are reserved for OEM= use */ }; =20 @@ -1096,7 +1103,123 @@ struct acpi_madt_multiproc_wakeup_mailbox { =20 #define ACPI_MP_WAKE_COMMAND_WAKEUP 1 =20 -/* 17: OEM data */ +/* Values for Version field above */ + +enum acpi_madt_core_pic_version { + ACPI_MADT_CORE_PIC_VERSION_NONE =3D 0, + ACPI_MADT_CORE_PIC_VERSION_V1 =3D 1, + ACPI_MADT_CORE_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_lio_pic_version { + ACPI_MADT_LIO_PIC_VERSION_NONE =3D 0, + ACPI_MADT_LIO_PIC_VERSION_V1 =3D 1, + ACPI_MADT_LIO_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_eio_pic_version { + ACPI_MADT_EIO_PIC_VERSION_NONE =3D 0, + ACPI_MADT_EIO_PIC_VERSION_V1 =3D 1, + ACPI_MADT_EIO_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_ht_pic_version { + ACPI_MADT_HT_PIC_VERSION_NONE =3D 0, + ACPI_MADT_HT_PIC_VERSION_V1 =3D 1, + ACPI_MADT_HT_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_bio_pic_version { + ACPI_MADT_BIO_PIC_VERSION_NONE =3D 0, + ACPI_MADT_BIO_PIC_VERSION_V1 =3D 1, + ACPI_MADT_BIO_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_msi_pic_version { + ACPI_MADT_MSI_PIC_VERSION_NONE =3D 0, + ACPI_MADT_MSI_PIC_VERSION_V1 =3D 1, + ACPI_MADT_MSI_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +enum acpi_madt_lpc_pic_version { + ACPI_MADT_LPC_PIC_VERSION_NONE =3D 0, + ACPI_MADT_LPC_PIC_VERSION_V1 =3D 1, + ACPI_MADT_LPC_PIC_VERSION_RESERVED =3D 2 /* 2 and greater are reserved */ +}; + +/* Core Interrupt Controller */ + +struct acpi_madt_core_pic { + struct acpi_subtable_header header; + u8 version; + u32 processor_id; + u32 core_id; + u32 flags; +}; + +/* Legacy I/O Interrupt Controller */ + +struct acpi_madt_lio_pic { + struct acpi_subtable_header header; + u8 version; + u64 address; + u16 size; + u8 cascade[2]; + u32 cascade_map[2]; +}; + +/* Extend I/O Interrupt Controller */ + +struct acpi_madt_eio_pic { + struct acpi_subtable_header header; + u8 version; + u8 cascade; + u8 node; + u64 node_map; +}; + +/* HT Interrupt Controller */ + +struct acpi_madt_ht_pic { + struct acpi_subtable_header header; + u8 version; + u64 address; + u16 size; + u8 cascade[8]; +}; + +/* Bridge I/O Interrupt Controller */ + +struct acpi_madt_bio_pic { + struct acpi_subtable_header header; + u8 version; + u64 address; + u16 size; + u16 id; + u16 gsi_base; +}; + +/* MSI Interrupt Controller */ + +struct acpi_madt_msi_pic { + struct acpi_subtable_header header; + u8 version; + u64 msg_address; + u32 start; + u32 count; +}; + +/* LPC Interrupt Controller */ + +struct acpi_madt_lpc_pic { + struct acpi_subtable_header header; + u8 version; + u64 address; + u16 size; + u8 cascade; +}; + +/* 80: OEM data */ =20 struct acpi_madt_oem_data { u8 oem_data[0]; --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E95A5C433EF for ; Fri, 15 Jul 2022 07:07:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231899AbiGOHHC (ORCPT ); Fri, 15 Jul 2022 03:07:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231143AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E7ECB74344 for ; Fri, 15 Jul 2022 00:06:09 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S4; Fri, 15 Jul 2022 15:05:57 +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 V15 02/15] APCI: irq: Add support for multiple GSI domains Date: Fri, 15 Jul 2022 15:05:38 +0800 Message-Id: <1657868751-30444-3-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S4 X-Coremail-Antispam: 1UD129KBjvJXoW3Ar4kJw1kur1fuFyxKF4fGrg_yoWfZF4rpF W3tw17ur42qF1jgFW8Ca15Za4akr10y3y2qayrG3srKw4qgF9xKFn7Ca42kFy5AFW5Xa1U ZF1aqa18CF1DAFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkE1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j 6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUdHU DUUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Marc Zyngier In an unfortunate departure from the ACPI spec, the LoongArch architecture split its GSI space across multiple interrupt controllers. In order to be able to reuse the core code and prevent architectures from reinventing an already square wheel, offer the arch code the ability to register a dispatcher function that will return the domain fwnode for a given GSI. The ARM GIC drivers are updated to support this (with a single domain, as intended). Signed-off-by: Marc Zyngier Cc: Hanjun Guo Cc: Lorenzo Pieralisi Signed-off-by: Jianmin Lv Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo --- drivers/acpi/irq.c | 40 +++++++++++++++++++++++++--------------- drivers/irqchip/irq-gic-v3.c | 18 ++++++++++++------ drivers/irqchip/irq-gic.c | 18 ++++++++++++------ include/linux/acpi.h | 2 +- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index c68e694..f0de768 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -12,7 +12,7 @@ =20 enum acpi_irq_model_id acpi_irq_model; =20 -static struct fwnode_handle *acpi_gsi_domain_id; +static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi); =20 /** * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI @@ -26,9 +26,10 @@ */ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) { - struct irq_domain *d =3D irq_find_matching_fwnode(acpi_gsi_domain_id, - DOMAIN_BUS_ANY); + struct irq_domain *d; =20 + d =3D irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi), + DOMAIN_BUS_ANY); *irq =3D irq_find_mapping(d, gsi); /* * *irq =3D=3D 0 means no mapping, that should @@ -53,12 +54,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int = trigger, { struct irq_fwspec fwspec; =20 - if (WARN_ON(!acpi_gsi_domain_id)) { + fwspec.fwnode =3D acpi_get_gsi_domain_id(gsi); + if (WARN_ON(!fwspec.fwnode)) { pr_warn("GSI: No registered irqchip, giving up\n"); return -EINVAL; } =20 - fwspec.fwnode =3D acpi_gsi_domain_id; fwspec.param[0] =3D gsi; fwspec.param[1] =3D acpi_dev_get_irq_type(trigger, polarity); fwspec.param_count =3D 2; @@ -73,13 +74,14 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int = trigger, */ void acpi_unregister_gsi(u32 gsi) { - struct irq_domain *d =3D irq_find_matching_fwnode(acpi_gsi_domain_id, - DOMAIN_BUS_ANY); + struct irq_domain *d; int irq; =20 if (WARN_ON(acpi_irq_model =3D=3D ACPI_IRQ_MODEL_GIC && gsi < 16)) return; =20 + d =3D irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi), + DOMAIN_BUS_ANY); irq =3D irq_find_mapping(d, gsi); irq_dispose_mapping(irq); } @@ -97,7 +99,8 @@ void acpi_unregister_gsi(u32 gsi) * The referenced device fwhandle or NULL on failure */ static struct fwnode_handle * -acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source) +acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source, + u32 gsi) { struct fwnode_handle *result; struct acpi_device *device; @@ -105,7 +108,7 @@ void acpi_unregister_gsi(u32 gsi) acpi_status status; =20 if (!source->string_length) - return acpi_gsi_domain_id; + return acpi_get_gsi_domain_id(gsi); =20 status =3D acpi_get_handle(NULL, source->string_ptr, &handle); if (WARN_ON(ACPI_FAILURE(status))) @@ -194,7 +197,7 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_re= source *ares, ctx->index -=3D irq->interrupt_count; return AE_OK; } - fwnode =3D acpi_gsi_domain_id; + fwnode =3D acpi_get_gsi_domain_id(irq->interrupts[ctx->index]); acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index], irq->triggering, irq->polarity, irq->shareable, ctx); @@ -207,7 +210,8 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_re= source *ares, ctx->index -=3D eirq->interrupt_count; return AE_OK; } - fwnode =3D acpi_get_irq_source_fwhandle(&eirq->resource_source); + fwnode =3D acpi_get_irq_source_fwhandle(&eirq->resource_source, + eirq->interrupts[ctx->index]); acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index], eirq->triggering, eirq->polarity, eirq->shareable, ctx); @@ -291,10 +295,10 @@ int acpi_irq_get(acpi_handle handle, unsigned int ind= ex, struct resource *res) * GSI interrupts */ void __init acpi_set_irq_model(enum acpi_irq_model_id model, - struct fwnode_handle *fwnode) + struct fwnode_handle *(*fn)(u32)) { acpi_irq_model =3D model; - acpi_gsi_domain_id =3D fwnode; + acpi_get_gsi_domain_id =3D fn; } =20 /** @@ -312,8 +316,14 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned = int flags, const struct irq_domain_ops *ops, void *host_data) { - struct irq_domain *d =3D irq_find_matching_fwnode(acpi_gsi_domain_id, - DOMAIN_BUS_ANY); + struct irq_domain *d; + + /* This only works for the GIC model... */ + if (acpi_irq_model !=3D ACPI_IRQ_MODEL_GIC) + return NULL; + + d =3D irq_find_matching_fwnode(acpi_get_gsi_domain_id(0), + DOMAIN_BUS_ANY); =20 if (!d) return NULL; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 5c1cf90..c664703 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -2360,11 +2360,17 @@ static void __init gic_acpi_setup_kvm_info(void) vgic_set_kvm_info(&gic_v3_kvm_info); } =20 +static struct fwnode_handle *gsi_domain_handle; + +static struct fwnode_handle *gic_v3_get_gsi_domain_id(u32 gsi) +{ + return gsi_domain_handle; +} + static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end) { struct acpi_madt_generic_distributor *dist; - struct fwnode_handle *domain_handle; size_t size; int i, err; =20 @@ -2396,18 +2402,18 @@ static void __init gic_acpi_setup_kvm_info(void) if (err) goto out_redist_unmap; =20 - domain_handle =3D irq_domain_alloc_fwnode(&dist->base_address); - if (!domain_handle) { + gsi_domain_handle =3D irq_domain_alloc_fwnode(&dist->base_address); + if (!gsi_domain_handle) { err =3D -ENOMEM; goto out_redist_unmap; } =20 err =3D gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs, - acpi_data.nr_redist_regions, 0, domain_handle); + acpi_data.nr_redist_regions, 0, gsi_domain_handle); if (err) goto out_fwhandle_free; =20 - acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle); + acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v3_get_gsi_domain_id); =20 if (static_branch_likely(&supports_deactivate_key)) gic_acpi_setup_kvm_info(); @@ -2415,7 +2421,7 @@ static void __init gic_acpi_setup_kvm_info(void) return 0; =20 out_fwhandle_free: - irq_domain_free_fwnode(domain_handle); + irq_domain_free_fwnode(gsi_domain_handle); out_redist_unmap: for (i =3D 0; i < acpi_data.nr_redist_regions; i++) if (acpi_data.redist_regs[i].redist_base) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 820404c..4c7bae0 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -1682,11 +1682,17 @@ static void __init gic_acpi_setup_kvm_info(void) vgic_set_kvm_info(&gic_v2_kvm_info); } =20 +static struct fwnode_handle *gsi_domain_handle; + +static struct fwnode_handle *gic_v2_get_gsi_domain_id(u32 gsi) +{ + return gsi_domain_handle; +} + static int __init gic_v2_acpi_init(union acpi_subtable_headers *header, const unsigned long end) { struct acpi_madt_generic_distributor *dist; - struct fwnode_handle *domain_handle; struct gic_chip_data *gic =3D &gic_data[0]; int count, ret; =20 @@ -1724,22 +1730,22 @@ static int __init gic_v2_acpi_init(union acpi_subta= ble_headers *header, /* * Initialize GIC instance zero (no multi-GIC support). */ - domain_handle =3D irq_domain_alloc_fwnode(&dist->base_address); - if (!domain_handle) { + gsi_domain_handle =3D irq_domain_alloc_fwnode(&dist->base_address); + if (!gsi_domain_handle) { pr_err("Unable to allocate domain handle\n"); gic_teardown(gic); return -ENOMEM; } =20 - ret =3D __gic_init_bases(gic, domain_handle); + ret =3D __gic_init_bases(gic, gsi_domain_handle); if (ret) { pr_err("Failed to initialise GIC\n"); - irq_domain_free_fwnode(domain_handle); + irq_domain_free_fwnode(gsi_domain_handle); gic_teardown(gic); return ret; } =20 - acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle); + acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v2_get_gsi_domain_id); =20 if (IS_ENABLED(CONFIG_ARM_GIC_V2M)) gicv2m_init(NULL, gic_data[0].domain); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4f82a5b..957e23f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -356,7 +356,7 @@ static inline bool acpi_sci_irq_valid(void) int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); =20 void acpi_set_irq_model(enum acpi_irq_model_id model, - struct fwnode_handle *fwnode); + struct fwnode_handle *(*)(u32)); =20 struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags, unsigned int size, --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DDFDC433EF for ; Fri, 15 Jul 2022 07:06:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231745AbiGOHG0 (ORCPT ); Fri, 15 Jul 2022 03:06:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230520AbiGOHGI (ORCPT ); Fri, 15 Jul 2022 03:06:08 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D5CBC3DBF3 for ; Fri, 15 Jul 2022 00:06:06 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S5; Fri, 15 Jul 2022 15:05:58 +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 V15 03/15] ACPI: irq: Allow acpi_gsi_to_irq() to have an arch-specific fallback Date: Fri, 15 Jul 2022 15:05:39 +0800 Message-Id: <1657868751-30444-4-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S5 X-Coremail-Antispam: 1UD129KBjvJXoWxZw1DKF18Jr43Xw4xAr4ruFg_yoW5WF4kpF Wxuw1xJrWIqr17ZrZ7C3yfuF13W3Z5JFWxXrW2k347CayDKF1agrnFgry2gryDAF4fCFWj v3ZIkFW8GF1DCa7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkE1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j 6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUdHU DUUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Marc Zyngier It appears that the generic version of acpi_gsi_to_irq() doesn't fallback to establishing a mapping if there is no pre-existing one while the x86 version does. While arm64 seems unaffected by it, LoongArch is relying on the x86 behaviour. In an effort to prevent new architectures from reinventing the proverbial wheel, provide an optional callback that the arch code can set to restore the x86 behaviour. Hopefully we can eventually get rid of this in the future once the expected behaviour has been clarified. Reported-by: Jianmin Lv Signed-off-by: Marc Zyngier Signed-off-by: Jianmin Lv Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo --- drivers/acpi/irq.c | 18 ++++++++++++++++-- include/linux/acpi.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index f0de768..dabe45e 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -13,6 +13,7 @@ enum acpi_irq_model_id acpi_irq_model; =20 static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi); +static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi); =20 /** * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI @@ -32,9 +33,12 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) DOMAIN_BUS_ANY); *irq =3D irq_find_mapping(d, gsi); /* - * *irq =3D=3D 0 means no mapping, that should - * be reported as a failure + * *irq =3D=3D 0 means no mapping, that should be reported as a + * failure, unless there is an arch-specific fallback handler. */ + if (!*irq && acpi_gsi_to_irq_fallback) + *irq =3D acpi_gsi_to_irq_fallback(gsi); + return (*irq > 0) ? 0 : -EINVAL; } EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); @@ -302,6 +306,16 @@ void __init acpi_set_irq_model(enum acpi_irq_model_id = model, } =20 /** + * acpi_set_gsi_to_irq_fallback - Register a GSI transfer + * callback to fallback to arch specified implementation. + * @fn: arch-specific fallback handler + */ +void __init acpi_set_gsi_to_irq_fallback(u32 (*fn)(u32)) +{ + acpi_gsi_to_irq_fallback =3D fn; +} + +/** * acpi_irq_create_hierarchy - Create a hierarchical IRQ domain with the d= efault * GSI domain as its parent. * @flags: Irq domain flags associated with the domain diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 957e23f..e2b60d5 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -357,6 +357,7 @@ static inline bool acpi_sci_irq_valid(void) =20 void acpi_set_irq_model(enum acpi_irq_model_id model, struct fwnode_handle *(*)(u32)); +void acpi_set_gsi_to_irq_fallback(u32 (*)(u32)); =20 struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags, unsigned int size, --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6E59C43334 for ; Fri, 15 Jul 2022 07:06:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231851AbiGOHGq (ORCPT ); Fri, 15 Jul 2022 03:06:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231245AbiGOHGN (ORCPT ); Fri, 15 Jul 2022 03:06:13 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 82E6F70993 for ; Fri, 15 Jul 2022 00:06:08 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S6; Fri, 15 Jul 2022 15:05:58 +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 V15 04/15] genirq/generic_chip: export irq_unmap_generic_chip Date: Fri, 15 Jul 2022 15:05:40 +0800 Message-Id: <1657868751-30444-5-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S6 X-Coremail-Antispam: 1UD129KBjvJXoW7AFy8uFy5JrWrKFy7CFykZrb_yoW8Xw18pa yrWa47WrWkGr18ZFWUGF1kuryavrs7GFW2ya1SvF92yr18Jws2gFykWrnavF40934xuFWY yFs7tFy8ur1UWFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkE1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j 6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUdHU DUUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Some irq controllers have to re-implement a private version for irq_generic_chip_ops, because they have a different xlate to translate hwirq. Export irq_unmap_generic_chip for reusing in user defined ops. Signed-off-by: Jianmin Lv --- include/linux/irq.h | 1 + kernel/irq/generic-chip.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 5053082..83a4574 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -1121,6 +1121,7 @@ struct irq_domain_chip_generic { /* Setup functions for irq_chip_generic */ int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw_irq); +void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq); struct irq_chip_generic * irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base, void __iomem *reg_base, irq_flow_handler_t handler); diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index f0862eb..c653cd3 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c @@ -431,7 +431,7 @@ int irq_map_generic_chip(struct irq_domain *d, unsigned= int virq, return 0; } =20 -static void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq) +void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq) { struct irq_data *data =3D irq_domain_get_irq_data(d, virq); struct irq_domain_chip_generic *dgc =3D d->gc; --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6707FC43334 for ; Fri, 15 Jul 2022 07:06:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231535AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230479AbiGOHGI (ORCPT ); Fri, 15 Jul 2022 03:06:08 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 94E3328710 for ; Fri, 15 Jul 2022 00:06:06 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S7; Fri, 15 Jul 2022 15:05:58 +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 V15 05/15] LoongArch: Use ACPI_GENERIC_GSI for gsi handling Date: Fri, 15 Jul 2022 15:05:41 +0800 Message-Id: <1657868751-30444-6-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S7 X-Coremail-Antispam: 1UD129KBjvJXoWxGF4DKry7tw1rZw47AFW8Zwb_yoW5AF48pr 4S9FnrJr4SqF18ZrW8t3s5uayUXryxKayIqa15J348J3srur1YvFn5Ar97XFy5tayrXrW8 Z3s5CFy5Jay3A3JanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkE1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j 6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUdHU DUUUUU= X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" For LoongArch, generic gsi code(driver/acpi/irq.c) can be reused after following patchs: APCI: irq: Add support for multiple GSI domains ACPI: irq: Allow acpi_gsi_to_irq() to have an arch-specific fallback So, config ACPI_GENERIC_GSI for LoongArch with removing the gsi code in arch directory. Signed-off-by: Jianmin Lv --- arch/loongarch/Kconfig | 1 + arch/loongarch/kernel/acpi.c | 65 ----------------------------------------= ---- 2 files changed, 1 insertion(+), 65 deletions(-) diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 1920d52..7f98fc0 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -112,6 +112,7 @@ config LOONGARCH select TRACE_IRQFLAGS_SUPPORT select USE_PERCPU_NUMA_NODE_ID select ZONE_DMA32 + select ACPI_GENERIC_GSI if ACPI =20 config 32BIT bool diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index bb729ee..03aa145 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -25,7 +25,6 @@ int acpi_strict =3D 1; /* We have no workarounds on LoongArch */ int num_processors; int disabled_cpus; -enum acpi_irq_model_id acpi_irq_model =3D ACPI_IRQ_MODEL_PLATFORM; =20 u64 acpi_saved_sp; =20 @@ -33,70 +32,6 @@ =20 #define PREFIX "ACPI: " =20 -int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp) -{ - if (irqp !=3D NULL) - *irqp =3D acpi_register_gsi(NULL, gsi, -1, -1); - return (*irqp >=3D 0) ? 0 : -EINVAL; -} -EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); - -int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi) -{ - if (gsi) - *gsi =3D isa_irq; - return 0; -} - -/* - * success: return IRQ number (>=3D0) - * failure: return < 0 - */ -int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polari= ty) -{ - struct irq_fwspec fwspec; - - switch (gsi) { - case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ: - fwspec.fwnode =3D liointc_domain->fwnode; - fwspec.param[0] =3D gsi - GSI_MIN_CPU_IRQ; - fwspec.param_count =3D 1; - - return irq_create_fwspec_mapping(&fwspec); - - case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ: - if (!pch_lpc_domain) - return -EINVAL; - - fwspec.fwnode =3D pch_lpc_domain->fwnode; - fwspec.param[0] =3D gsi - GSI_MIN_LPC_IRQ; - fwspec.param[1] =3D acpi_dev_get_irq_type(trigger, polarity); - fwspec.param_count =3D 2; - - return irq_create_fwspec_mapping(&fwspec); - - case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ: - if (!pch_pic_domain[0]) - return -EINVAL; - - fwspec.fwnode =3D pch_pic_domain[0]->fwnode; - fwspec.param[0] =3D gsi - GSI_MIN_PCH_IRQ; - fwspec.param[1] =3D IRQ_TYPE_LEVEL_HIGH; - fwspec.param_count =3D 2; - - return irq_create_fwspec_mapping(&fwspec); - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(acpi_register_gsi); - -void acpi_unregister_gsi(u32 gsi) -{ - -} -EXPORT_SYMBOL_GPL(acpi_unregister_gsi); - void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long s= ize) { =20 --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 414DEC433EF for ; Fri, 15 Jul 2022 07:06:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231820AbiGOHGi (ORCPT ); Fri, 15 Jul 2022 03:06:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231195AbiGOHGL (ORCPT ); Fri, 15 Jul 2022 03:06:11 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 02C9D61DBC for ; Fri, 15 Jul 2022 00:06:06 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S8; Fri, 15 Jul 2022 15:05:58 +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 V15 06/15] irqchip: Add Loongson PCH LPC controller support Date: Fri, 15 Jul 2022 15:05:42 +0800 Message-Id: <1657868751-30444-7-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S8 X-Coremail-Antispam: 1UD129KBjvJXoW3JFW8Ww4xuF1kCrWxuryrCrg_yoWfZr15pF W5Z347Xr4UXF4jqr1kCa1UZrWayw1fKayjka93Ga43Jr9rZryvkF1vvFnruFs8AF4agFWa vFsxtFy8uF1UA3JanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvj1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWU JVW8JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUoO J5UUUUU X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen PCH-LPC stands for "LPC Interrupts" that described in Section 24.3 of "Loongson 7A1000 Bridge User Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 4 +- arch/loongarch/kernel/irq.c | 1 - drivers/irqchip/Kconfig | 8 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-loongson-pch-lpc.c | 208 +++++++++++++++++++++++++++++= ++++ 5 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 drivers/irqchip/irq-loongson-pch-lpc.c diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index ace3ea6..48c0ce4 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -104,7 +104,7 @@ struct irq_domain *eiointc_acpi_init(struct irq_domain = *parent, =20 struct irq_domain *htvec_acpi_init(struct irq_domain *parent, struct acpi_madt_ht_pic *acpi_htvec); -struct irq_domain *pch_lpc_acpi_init(struct irq_domain *parent, +int pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc); struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi); @@ -121,7 +121,7 @@ struct irq_domain *pch_pic_acpi_init(struct irq_domain = *parent, =20 extern struct irq_domain *cpu_domain; extern struct irq_domain *liointc_domain; -extern struct irq_domain *pch_lpc_domain; +extern struct fwnode_handle *pch_lpc_handle; extern struct irq_domain *pch_msi_domain[MAX_IO_PICS]; extern struct irq_domain *pch_pic_domain[MAX_IO_PICS]; =20 diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index b34b8d7..07d6059 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -27,7 +27,6 @@ =20 struct irq_domain *cpu_domain; struct irq_domain *liointc_domain; -struct irq_domain *pch_lpc_domain; struct irq_domain *pch_msi_domain[MAX_IO_PICS]; struct irq_domain *pch_pic_domain[MAX_IO_PICS]; =20 diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 1f23a6b..c1d527f 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -591,6 +591,14 @@ config LOONGSON_PCH_MSI help Support for the Loongson PCH MSI Controller. =20 +config LOONGSON_PCH_LPC + bool "Loongson PCH LPC Controller" + depends on MACH_LOONGSON64 + default (MACH_LOONGSON64 && LOONGARCH) + select IRQ_DOMAIN_HIERARCHY + help + Support for the Loongson PCH LPC Controller. + config MST_IRQ bool "MStar Interrupt Controller" depends on ARCH_MEDIATEK || ARCH_MSTARV7 || COMPILE_TEST diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5b67450..242b8b3 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_LOONGSON_HTPIC) +=3D irq-loongson-htpic.o obj-$(CONFIG_LOONGSON_HTVEC) +=3D irq-loongson-htvec.o obj-$(CONFIG_LOONGSON_PCH_PIC) +=3D irq-loongson-pch-pic.o obj-$(CONFIG_LOONGSON_PCH_MSI) +=3D irq-loongson-pch-msi.o +obj-$(CONFIG_LOONGSON_PCH_LPC) +=3D irq-loongson-pch-lpc.o obj-$(CONFIG_MST_IRQ) +=3D irq-mst-intc.o obj-$(CONFIG_SL28CPLD_INTC) +=3D irq-sl28cpld.o obj-$(CONFIG_MACH_REALTEK_RTL) +=3D irq-realtek-rtl.o diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-l= oongson-pch-lpc.c new file mode 100644 index 0000000..3f51184 --- /dev/null +++ b/drivers/irqchip/irq-loongson-pch-lpc.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Loongson LPC Interrupt Controller support + * + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited + */ + +#define pr_fmt(fmt) "lpc: " fmt + +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define LPC_INT_CTL 0x00 +#define LPC_INT_ENA 0x04 +#define LPC_INT_STS 0x08 +#define LPC_INT_CLR 0x0c +#define LPC_INT_POL 0x10 +#define LPC_COUNT 16 + +/* LPC_INT_CTL */ +#define LPC_INT_CTL_EN BIT(31) + +struct pch_lpc { + void __iomem *base; + struct irq_domain *lpc_domain; + raw_spinlock_t lpc_lock; + u32 saved_reg_ctl; + u32 saved_reg_ena; + u32 saved_reg_pol; +}; + +struct fwnode_handle *pch_lpc_handle; + +static void lpc_irq_ack(struct irq_data *d) +{ + unsigned long flags; + struct pch_lpc *priv =3D d->domain->host_data; + + raw_spin_lock_irqsave(&priv->lpc_lock, flags); + writel(0x1 << d->hwirq, priv->base + LPC_INT_CLR); + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); +} + +static void lpc_irq_mask(struct irq_data *d) +{ + unsigned long flags; + struct pch_lpc *priv =3D d->domain->host_data; + + raw_spin_lock_irqsave(&priv->lpc_lock, flags); + writel(readl(priv->base + LPC_INT_ENA) & (~(0x1 << (d->hwirq))), + priv->base + LPC_INT_ENA); + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); +} + +static void lpc_irq_unmask(struct irq_data *d) +{ + unsigned long flags; + struct pch_lpc *priv =3D d->domain->host_data; + + raw_spin_lock_irqsave(&priv->lpc_lock, flags); + writel(readl(priv->base + LPC_INT_ENA) | (0x1 << (d->hwirq)), + priv->base + LPC_INT_ENA); + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); +} + +static int lpc_irq_set_type(struct irq_data *d, unsigned int type) +{ + u32 val; + u32 mask =3D 0x1 << (d->hwirq); + struct pch_lpc *priv =3D d->domain->host_data; + + if (!(type & IRQ_TYPE_LEVEL_MASK)) + return 0; + + val =3D readl(priv->base + LPC_INT_POL); + + if (type =3D=3D IRQ_TYPE_LEVEL_HIGH) + val |=3D mask; + else + val &=3D ~mask; + + writel(val, priv->base + LPC_INT_POL); + + return 0; +} + +static const struct irq_chip pch_lpc_irq_chip =3D { + .name =3D "PCH LPC", + .irq_mask =3D lpc_irq_mask, + .irq_unmask =3D lpc_irq_unmask, + .irq_ack =3D lpc_irq_ack, + .irq_set_type =3D lpc_irq_set_type, + .flags =3D IRQCHIP_SKIP_SET_WAKE, +}; + +static void lpc_irq_dispatch(struct irq_desc *desc) +{ + u32 pending, bit; + struct irq_chip *chip =3D irq_desc_get_chip(desc); + struct pch_lpc *priv =3D irq_desc_get_handler_data(desc); + + chained_irq_enter(chip, desc); + + pending =3D readl(priv->base + LPC_INT_ENA); + pending &=3D readl(priv->base + LPC_INT_STS); + if (!pending) + spurious_interrupt(); + + while (pending) { + bit =3D __ffs(pending); + + generic_handle_domain_irq(priv->lpc_domain, bit); + pending &=3D ~BIT(bit); + } + chained_irq_exit(chip, desc); +} + +static int pch_lpc_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(irq, &pch_lpc_irq_chip, handle_level_irq); + return 0; +} + +static const struct irq_domain_ops pch_lpc_domain_ops =3D { + .map =3D pch_lpc_map, + .translate =3D irq_domain_translate_twocell, +}; + +static void pch_lpc_reset(struct pch_lpc *priv) +{ + /* Enable the LPC interrupt, bit31: en bit30: edge */ + writel(LPC_INT_CTL_EN, priv->base + LPC_INT_CTL); + writel(0, priv->base + LPC_INT_ENA); + /* Clear all 18-bit interrpt bit */ + writel(GENMASK(17, 0), priv->base + LPC_INT_CLR); +} + +static int pch_lpc_disabled(struct pch_lpc *priv) +{ + return (readl(priv->base + LPC_INT_ENA) =3D=3D 0xffffffff) && + (readl(priv->base + LPC_INT_STS) =3D=3D 0xffffffff); +} + +int __init pch_lpc_acpi_init(struct irq_domain *parent, + struct acpi_madt_lpc_pic *acpi_pchlpc) +{ + int parent_irq; + struct pch_lpc *priv; + struct irq_fwspec fwspec; + struct fwnode_handle *irq_handle; + + if (!acpi_pchlpc) + return -EINVAL; + + priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + raw_spin_lock_init(&priv->lpc_lock); + + priv->base =3D ioremap(acpi_pchlpc->address, acpi_pchlpc->size); + if (!priv->base) + goto free_priv; + + if (pch_lpc_disabled(priv)) { + pr_err("Failed to get LPC status\n"); + goto iounmap_base; + } + + irq_handle =3D irq_domain_alloc_named_fwnode("lpcintc"); + if (!irq_handle) { + pr_err("Unable to allocate domain handle\n"); + goto iounmap_base; + } + + priv->lpc_domain =3D irq_domain_create_linear(irq_handle, LPC_COUNT, + &pch_lpc_domain_ops, priv); + if (!priv->lpc_domain) { + pr_err("Failed to create IRQ domain\n"); + goto free_irq_handle; + } + pch_lpc_reset(priv); + + fwspec.fwnode =3D parent->fwnode; + fwspec.param[0] =3D acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; + fwspec.param[1] =3D IRQ_TYPE_LEVEL_HIGH; + fwspec.param_count =3D 2; + parent_irq =3D irq_create_fwspec_mapping(&fwspec); + irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv); + + pch_lpc_handle =3D irq_handle; + return 0; + +free_irq_handle: + irq_domain_free_fwnode(irq_handle); +iounmap_base: + iounmap(priv->base); +free_priv: + kfree(priv); + + return -ENOMEM; +} --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5554FC433EF for ; Fri, 15 Jul 2022 07:06:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231702AbiGOHGV (ORCPT ); Fri, 15 Jul 2022 03:06:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230515AbiGOHGI (ORCPT ); Fri, 15 Jul 2022 03:06:08 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 32AF96E895 for ; Fri, 15 Jul 2022 00:06:06 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S9; Fri, 15 Jul 2022 15:05:59 +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 V15 07/15] irqchip: remove COMPILE_TEST for pch-pic and pch-msi Date: Fri, 15 Jul 2022 15:05:43 +0800 Message-Id: <1657868751-30444-8-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S9 X-Coremail-Antispam: 1UD129KBjvdXoW7GFy5Zw1rKF1fAFyfWryxAFb_yoWkXrb_Ca y7KFs7JFnrCrW7G347Wr4xWryjyayj9wnF9a48tr13X3WIqw4fW3W7Can8GF17ua4UKFsr u3yfCrs7Cr1SvjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUIcSsGvfJTRUUUbxxFc2x0x2IEx4CE42xK8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AK wVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84ACjcxK6xIIjxv20x vE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1l84ACjcxK6I8E 87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AIxVAIcxkEcV Aq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r1j 6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64 vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26ryrJr1UJwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F4 0E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFyl IxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxV AFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWU JVW8JwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUoO J5UUUUU X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen Loongson's pch-pic and pch-msi will have some arch-specific code, so we remove the COMPILE_TEST dependency to avoid build warnings. Signed-off-by: Huacai Chen Signed-off-by: Jianmin Lv --- drivers/irqchip/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index c1d527f..8844e6b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -574,7 +574,7 @@ config LOONGSON_HTVEC =20 config LOONGSON_PCH_PIC bool "Loongson PCH PIC Controller" - depends on MACH_LOONGSON64 || COMPILE_TEST + depends on MACH_LOONGSON64 default MACH_LOONGSON64 select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS @@ -583,7 +583,7 @@ config LOONGSON_PCH_PIC =20 config LOONGSON_PCH_MSI bool "Loongson PCH MSI Controller" - depends on MACH_LOONGSON64 || COMPILE_TEST + depends on MACH_LOONGSON64 depends on PCI default MACH_LOONGSON64 select IRQ_DOMAIN_HIERARCHY --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87383C433EF for ; Fri, 15 Jul 2022 07:07:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231926AbiGOHHM (ORCPT ); Fri, 15 Jul 2022 03:07:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231569AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E7F7D74347 for ; Fri, 15 Jul 2022 00:06:09 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S10; Fri, 15 Jul 2022 15:05:59 +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 V15 08/15] irqchip/loongson-pch-pic: Add ACPI init support Date: Fri, 15 Jul 2022 15:05:44 +0800 Message-Id: <1657868751-30444-9-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S10 X-Coremail-Antispam: 1UD129KBjvJXoW3Aw1UGw43tFWUXFWkuF18AFb_yoWDGF45pF W5AwsxXr4UJr17Wry0kws8Zryay34a9a12gaySkFn3Jw4DXryvgF10yF1qkF1rAF45AF47 Zrs3K3Wj9a1UAaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv01xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUb XdbUUUUUU== X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen PCH-PIC/PCH-MSI stands for "Interrupt Controller" that described in Section 5 of "Loongson 7A1000 Bridge User Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 5 +- arch/loongarch/kernel/irq.c | 1 - arch/mips/include/asm/mach-loongson64/irq.h | 2 +- drivers/irqchip/irq-loongson-pch-pic.c | 178 +++++++++++++++++++++++-= ---- 4 files changed, 151 insertions(+), 35 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index 48c0ce4..74fef60 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -108,8 +108,9 @@ int pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc); struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi); -struct irq_domain *pch_pic_acpi_init(struct irq_domain *parent, +int pch_pic_acpi_init(struct irq_domain *parent, struct acpi_madt_bio_pic *acpi_pchpic); +int find_pch_pic(u32 gsi); =20 extern struct acpi_madt_lio_pic *acpi_liointc; extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS]; @@ -123,7 +124,7 @@ struct irq_domain *pch_pic_acpi_init(struct irq_domain = *parent, extern struct irq_domain *liointc_domain; extern struct fwnode_handle *pch_lpc_handle; extern struct irq_domain *pch_msi_domain[MAX_IO_PICS]; -extern struct irq_domain *pch_pic_domain[MAX_IO_PICS]; +extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; =20 extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev); =20 diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 07d6059..866b2ee 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -28,7 +28,6 @@ struct irq_domain *cpu_domain; struct irq_domain *liointc_domain; struct irq_domain *pch_msi_domain[MAX_IO_PICS]; -struct irq_domain *pch_pic_domain[MAX_IO_PICS]; =20 /* * 'what should we do if we get a hw irq event on an illegal vector'. diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/includ= e/asm/mach-loongson64/irq.h index 98ea977..55e0dee 100644 --- a/arch/mips/include/asm/mach-loongson64/irq.h +++ b/arch/mips/include/asm/mach-loongson64/irq.h @@ -7,7 +7,7 @@ #define NR_MIPS_CPU_IRQS 8 #define NR_MAX_CHAINED_IRQS 40 /* Chained IRQs means those not directly us= ed by devices */ #define NR_IRQS (NR_IRQS_LEGACY + NR_MIPS_CPU_IRQS + NR_MAX_CHAINED_IRQS= + 256) - +#define MAX_IO_PICS 1 #define MIPS_CPU_IRQ_BASE NR_IRQS_LEGACY =20 #include diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-l= oongson-pch-pic.c index a4eb8a2..b6a73c8 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -33,13 +33,40 @@ #define PIC_REG_IDX(irq_id) ((irq_id) / PIC_COUNT_PER_REG) #define PIC_REG_BIT(irq_id) ((irq_id) % PIC_COUNT_PER_REG) =20 +static int nr_pics; + struct pch_pic { void __iomem *base; struct irq_domain *pic_domain; u32 ht_vec_base; raw_spinlock_t pic_lock; + u32 vec_count; + u32 gsi_base; }; =20 +static struct pch_pic *pch_pic_priv[MAX_IO_PICS]; + +struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; + +int find_pch_pic(u32 gsi) +{ + int i; + + /* Find the PCH_PIC that manages this GSI. */ + for (i =3D 0; i < MAX_IO_PICS; i++) { + struct pch_pic *priv =3D pch_pic_priv[i]; + + if (!priv) + return -1; + + if (gsi >=3D priv->gsi_base && gsi < (priv->gsi_base + priv->vec_count)) + return i; + } + + pr_err("ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi); + return -1; +} + static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit) { u32 reg; @@ -139,6 +166,28 @@ static void pch_pic_ack_irq(struct irq_data *d) .irq_set_type =3D pch_pic_set_type, }; =20 +static int pch_pic_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + struct pch_pic *priv =3D d->host_data; + struct device_node *of_node =3D to_of_node(fwspec->fwnode); + + if (fwspec->param_count < 1) + return -EINVAL; + + if (of_node) { + *hwirq =3D fwspec->param[0] + priv->ht_vec_base; + *type =3D fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + } else { + *hwirq =3D fwspec->param[0] - priv->gsi_base; + *type =3D IRQ_TYPE_NONE; + } + + return 0; +} + static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { @@ -149,13 +198,13 @@ static int pch_pic_alloc(struct irq_domain *domain, u= nsigned int virq, struct irq_fwspec parent_fwspec; struct pch_pic *priv =3D domain->host_data; =20 - err =3D irq_domain_translate_twocell(domain, fwspec, &hwirq, &type); + err =3D pch_pic_domain_translate(domain, fwspec, &hwirq, &type); if (err) return err; =20 parent_fwspec.fwnode =3D domain->parent->fwnode; parent_fwspec.param_count =3D 1; - parent_fwspec.param[0] =3D hwirq + priv->ht_vec_base; + parent_fwspec.param[0] =3D hwirq; =20 err =3D irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); if (err) @@ -170,7 +219,7 @@ static int pch_pic_alloc(struct irq_domain *domain, uns= igned int virq, } =20 static const struct irq_domain_ops pch_pic_domain_ops =3D { - .translate =3D irq_domain_translate_twocell, + .translate =3D pch_pic_domain_translate, .alloc =3D pch_pic_alloc, .free =3D irq_domain_free_irqs_parent, }; @@ -180,7 +229,7 @@ static void pch_pic_reset(struct pch_pic *priv) int i; =20 for (i =3D 0; i < PIC_COUNT; i++) { - /* Write vectored ID */ + /* Write vector ID */ writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i)); /* Hardcode route to HT0 Lo */ writeb(1, priv->base + PCH_INT_ROUTE(i)); @@ -198,50 +247,37 @@ static void pch_pic_reset(struct pch_pic *priv) } } =20 -static int pch_pic_of_init(struct device_node *node, - struct device_node *parent) +static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base, + struct irq_domain *parent_domain, struct fwnode_handle *domain_handle, + u32 gsi_base) { struct pch_pic *priv; - struct irq_domain *parent_domain; - int err; =20 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; =20 raw_spin_lock_init(&priv->pic_lock); - priv->base =3D of_iomap(node, 0); - if (!priv->base) { - err =3D -ENOMEM; + priv->base =3D ioremap(addr, size); + if (!priv->base) goto free_priv; - } - - parent_domain =3D irq_find_host(parent); - if (!parent_domain) { - pr_err("Failed to find the parent domain\n"); - err =3D -ENXIO; - goto iounmap_base; - } =20 - if (of_property_read_u32(node, "loongson,pic-base-vec", - &priv->ht_vec_base)) { - pr_err("Failed to determine pic-base-vec\n"); - err =3D -EINVAL; - goto iounmap_base; - } + priv->ht_vec_base =3D vec_base; + priv->vec_count =3D ((readq(priv->base) >> 48) & 0xff) + 1; + priv->gsi_base =3D gsi_base; =20 priv->pic_domain =3D irq_domain_create_hierarchy(parent_domain, 0, - PIC_COUNT, - of_node_to_fwnode(node), - &pch_pic_domain_ops, - priv); + priv->vec_count, domain_handle, + &pch_pic_domain_ops, priv); + if (!priv->pic_domain) { pr_err("Failed to create IRQ domain\n"); - err =3D -ENOMEM; goto iounmap_base; } =20 pch_pic_reset(priv); + pch_pic_handle[nr_pics] =3D domain_handle; + pch_pic_priv[nr_pics++] =3D priv; =20 return 0; =20 @@ -250,7 +286,87 @@ static int pch_pic_of_init(struct device_node *node, free_priv: kfree(priv); =20 - return err; + return -EINVAL; +} + +#ifdef CONFIG_OF + +static int pch_pic_of_init(struct device_node *node, + struct device_node *parent) +{ + int err, vec_base; + struct resource res; + struct irq_domain *parent_domain; + + if (of_address_to_resource(node, 0, &res)) + return -EINVAL; + + parent_domain =3D irq_find_host(parent); + if (!parent_domain) { + pr_err("Failed to find the parent domain\n"); + return -ENXIO; + } + + if (of_property_read_u32(node, "loongson,pic-base-vec", &vec_base)) { + pr_err("Failed to determine pic-base-vec\n"); + return -EINVAL; + } + + err =3D pch_pic_init(res.start, resource_size(&res), vec_base, + parent_domain, of_node_to_fwnode(node), 0); + if (err < 0) + return err; + + return 0; } =20 IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init); + +#endif + +#ifdef CONFIG_ACPI +static int __init +lpcintc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_lpc_pic *lpcintc_entry =3D (struct acpi_madt_lpc_pic *)h= eader; + + return pch_lpc_acpi_init(pch_pic_priv[0]->pic_domain, lpcintc_entry); +} + +static int __init acpi_cascade_irqdomain_init(void) +{ + acpi_table_parse_madt(ACPI_MADT_TYPE_LPC_PIC, + lpcintc_parse_madt, 0); + return 0; +} + +int __init pch_pic_acpi_init(struct irq_domain *parent, + struct acpi_madt_bio_pic *acpi_pchpic) +{ + int ret, vec_base; + struct fwnode_handle *domain_handle; + + if (!acpi_pchpic) + return -EINVAL; + + vec_base =3D acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ; + + domain_handle =3D irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchpic); + if (!domain_handle) { + pr_err("Unable to allocate domain handle\n"); + return -ENOMEM; + } + + ret =3D pch_pic_init(acpi_pchpic->address, acpi_pchpic->size, + vec_base, parent, domain_handle, acpi_pchpic->gsi_base); + + if (!ret) { + if (acpi_pchpic->id =3D=3D 0) + acpi_cascade_irqdomain_init(); + } else + irq_domain_free_fwnode(domain_handle); + + return ret; +} +#endif --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55AFDC43334 for ; Fri, 15 Jul 2022 07:06:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231866AbiGOHGt (ORCPT ); Fri, 15 Jul 2022 03:06:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231281AbiGOHGO (ORCPT ); Fri, 15 Jul 2022 03:06:14 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 001067358C for ; Fri, 15 Jul 2022 00:06:08 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S11; Fri, 15 Jul 2022 15:06:00 +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 V15 09/15] irqchip/loongson-pch-msi: Add ACPI init support Date: Fri, 15 Jul 2022 15:05:45 +0800 Message-Id: <1657868751-30444-10-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S11 X-Coremail-Antispam: 1UD129KBjvJXoW3Aw1UGw43tF1xJF48CFyrCrg_yoW3Ar18pF W3A39Fqr48G34UWrWvkF4DZryayFySkFsFqa1fC3Z3tw4qyr9YgF18JF129F15ArWUWF1a vr1xKa1UuF4DAa7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv01xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUb XdbUUUUUU== X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen PCH-PIC/PCH-MSI stands for "Interrupt Controller" that described in Section 5 of "Loongson 7A1000 Bridge User Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 4 +- arch/loongarch/kernel/irq.c | 1 - drivers/irqchip/irq-loongson-pch-msi.c | 131 ++++++++++++++++++++++-------= ---- 3 files changed, 91 insertions(+), 45 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index 74fef60..6022406 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -106,11 +106,12 @@ struct irq_domain *htvec_acpi_init(struct irq_domain = *parent, struct acpi_madt_ht_pic *acpi_htvec); int pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc); -struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent, +int pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi); int pch_pic_acpi_init(struct irq_domain *parent, struct acpi_madt_bio_pic *acpi_pchpic); int find_pch_pic(u32 gsi); +struct fwnode_handle *get_pch_msi_handle(int pci_segment); =20 extern struct acpi_madt_lio_pic *acpi_liointc; extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS]; @@ -123,7 +124,6 @@ int pch_pic_acpi_init(struct irq_domain *parent, extern struct irq_domain *cpu_domain; extern struct irq_domain *liointc_domain; extern struct fwnode_handle *pch_lpc_handle; -extern struct irq_domain *pch_msi_domain[MAX_IO_PICS]; extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; =20 extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev); diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 866b2ee..ce21281 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -27,7 +27,6 @@ =20 struct irq_domain *cpu_domain; struct irq_domain *liointc_domain; -struct irq_domain *pch_msi_domain[MAX_IO_PICS]; =20 /* * 'what should we do if we get a hw irq event on an illegal vector'. diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-l= oongson-pch-msi.c index e3801c4..b3f1f8e 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -15,6 +15,8 @@ #include #include =20 +static int nr_pics; + struct pch_msi_data { struct mutex msi_map_lock; phys_addr_t doorbell; @@ -23,6 +25,8 @@ struct pch_msi_data { unsigned long *msi_map; }; =20 +static struct fwnode_handle *pch_msi_handle[MAX_IO_PICS]; + static void pch_msi_mask_msi_irq(struct irq_data *d) { pci_msi_mask_irq(d); @@ -154,12 +158,12 @@ static void pch_msi_middle_domain_free(struct irq_dom= ain *domain, }; =20 static int pch_msi_init_domains(struct pch_msi_data *priv, - struct device_node *node, - struct irq_domain *parent) + struct irq_domain *parent, + struct fwnode_handle *domain_handle) { struct irq_domain *middle_domain, *msi_domain; =20 - middle_domain =3D irq_domain_create_linear(of_node_to_fwnode(node), + middle_domain =3D irq_domain_create_linear(domain_handle, priv->num_irqs, &pch_msi_middle_domain_ops, priv); @@ -171,7 +175,7 @@ static int pch_msi_init_domains(struct pch_msi_data *pr= iv, middle_domain->parent =3D parent; irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); =20 - msi_domain =3D pci_msi_create_irq_domain(of_node_to_fwnode(node), + msi_domain =3D pci_msi_create_irq_domain(domain_handle, &pch_msi_domain_info, middle_domain); if (!msi_domain) { @@ -183,19 +187,11 @@ static int pch_msi_init_domains(struct pch_msi_data *= priv, return 0; } =20 -static int pch_msi_init(struct device_node *node, - struct device_node *parent) +static int pch_msi_init(phys_addr_t msg_address, int irq_base, int irq_cou= nt, + struct irq_domain *parent_domain, struct fwnode_handle *domain_handle) { - struct pch_msi_data *priv; - struct irq_domain *parent_domain; - struct resource res; int ret; - - parent_domain =3D irq_find_host(parent); - if (!parent_domain) { - pr_err("Failed to find the parent domain\n"); - return -ENXIO; - } + struct pch_msi_data *priv; =20 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -203,48 +199,99 @@ static int pch_msi_init(struct device_node *node, =20 mutex_init(&priv->msi_map_lock); =20 - ret =3D of_address_to_resource(node, 0, &res); - if (ret) { - pr_err("Failed to allocate resource\n"); - goto err_priv; - } - - priv->doorbell =3D res.start; - - if (of_property_read_u32(node, "loongson,msi-base-vec", - &priv->irq_first)) { - pr_err("Unable to parse MSI vec base\n"); - ret =3D -EINVAL; - goto err_priv; - } - - if (of_property_read_u32(node, "loongson,msi-num-vecs", - &priv->num_irqs)) { - pr_err("Unable to parse MSI vec number\n"); - ret =3D -EINVAL; - goto err_priv; - } + priv->doorbell =3D msg_address; + priv->irq_first =3D irq_base; + priv->num_irqs =3D irq_count; =20 priv->msi_map =3D bitmap_zalloc(priv->num_irqs, GFP_KERNEL); - if (!priv->msi_map) { - ret =3D -ENOMEM; + if (!priv->msi_map) goto err_priv; - } =20 pr_debug("Registering %d MSIs, starting at %d\n", priv->num_irqs, priv->irq_first); =20 - ret =3D pch_msi_init_domains(priv, node, parent_domain); + ret =3D pch_msi_init_domains(priv, parent_domain, domain_handle); if (ret) goto err_map; =20 + pch_msi_handle[nr_pics++] =3D domain_handle; return 0; =20 err_map: bitmap_free(priv->msi_map); err_priv: kfree(priv); - return ret; + + return -EINVAL; +} + +#ifdef CONFIG_OF +static int pch_msi_of_init(struct device_node *node, struct device_node *p= arent) +{ + int err; + int irq_base, irq_count; + struct resource res; + struct irq_domain *parent_domain; + + parent_domain =3D irq_find_host(parent); + if (!parent_domain) { + pr_err("Failed to find the parent domain\n"); + return -ENXIO; + } + + if (of_address_to_resource(node, 0, &res)) { + pr_err("Failed to allocate resource\n"); + return -EINVAL; + } + + if (of_property_read_u32(node, "loongson,msi-base-vec", &irq_base)) { + pr_err("Unable to parse MSI vec base\n"); + return -EINVAL; + } + + if (of_property_read_u32(node, "loongson,msi-num-vecs", &irq_count)) { + pr_err("Unable to parse MSI vec number\n"); + return -EINVAL; + } + + err =3D pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_no= de_to_fwnode(node)); + if (err < 0) + return err; + + return 0; +} + +IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init); +#endif + +#ifdef CONFIG_ACPI +struct fwnode_handle *get_pch_msi_handle(int pci_segment) +{ + int i; + + for (i =3D 0; i < MAX_IO_PICS; i++) { + if (msi_group[i].pci_segment =3D=3D pci_segment) + return pch_msi_handle[i]; + } + return NULL; } =20 -IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init); +int __init pch_msi_acpi_init(struct irq_domain *parent, + struct acpi_madt_msi_pic *acpi_pchmsi) +{ + int ret; + struct fwnode_handle *domain_handle; + + if (!acpi_pchmsi) + return -EINVAL; + + domain_handle =3D irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchmsi); + + ret =3D pch_msi_init(acpi_pchmsi->msg_address, acpi_pchmsi->start, + acpi_pchmsi->count, parent, domain_handle); + if (ret < 0) + irq_domain_free_fwnode(domain_handle); + + return ret; +} +#endif --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37DECC433EF for ; Fri, 15 Jul 2022 07:07:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231890AbiGOHG6 (ORCPT ); Fri, 15 Jul 2022 03:06:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231359AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 1BA5A735B4 for ; Fri, 15 Jul 2022 00:06:08 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S12; Fri, 15 Jul 2022 15:06:00 +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 V15 10/15] irqchip/loongson-htvec: Add ACPI init support Date: Fri, 15 Jul 2022 15:05:46 +0800 Message-Id: <1657868751-30444-11-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S12 X-Coremail-Antispam: 1UD129KBjvJXoWxKrykGw1fGr13Kr4fWr17Wrg_yoWxGF4fpF W5A3yYqrWUJFyxurykGa1DZry3A345Wa9rtFWSk3WSywsrCw1DCF18AF1jkF13CFW0va1Y 9r4F93W5WF4UCaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv01xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUb XdbUUUUUU== X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen HTVECINTC stands for "HyperTransport Interrupts" that described in Section 14.3 of "Loongson 3A5000 Processor Reference Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 2 +- drivers/irqchip/irq-loongson-htvec.c | 145 +++++++++++++++++++++++++++----= ---- 2 files changed, 112 insertions(+), 35 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index 6022406..8775dc6 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -102,7 +102,7 @@ struct irq_domain *liointc_acpi_init(struct irq_domain = *parent, struct irq_domain *eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc); =20 -struct irq_domain *htvec_acpi_init(struct irq_domain *parent, +int htvec_acpi_init(struct irq_domain *parent, struct acpi_madt_ht_pic *acpi_htvec); int pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc); diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loo= ngson-htvec.c index 60a335d..65f4938 100644 --- a/drivers/irqchip/irq-loongson-htvec.c +++ b/drivers/irqchip/irq-loongson-htvec.c @@ -20,7 +20,6 @@ /* Registers */ #define HTVEC_EN_OFF 0x20 #define HTVEC_MAX_PARENT_IRQ 8 - #define VEC_COUNT_PER_REG 32 #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) @@ -32,6 +31,8 @@ struct htvec { raw_spinlock_t htvec_lock; }; =20 +static struct htvec *htvec_priv; + static void htvec_irq_dispatch(struct irq_desc *desc) { int i; @@ -155,64 +156,140 @@ static void htvec_reset(struct htvec *priv) } } =20 -static int htvec_of_init(struct device_node *node, - struct device_node *parent) +static int htvec_init(phys_addr_t addr, unsigned long size, + int num_parents, int parent_irq[], struct fwnode_handle *domain_handle) { + int i; struct htvec *priv; - int err, parent_irq[8], i; =20 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; =20 + priv->num_parents =3D num_parents; + priv->base =3D ioremap(addr, size); raw_spin_lock_init(&priv->htvec_lock); - priv->base =3D of_iomap(node, 0); - if (!priv->base) { - err =3D -ENOMEM; - goto free_priv; - } - - /* Interrupt may come from any of the 8 interrupt lines */ - for (i =3D 0; i < HTVEC_MAX_PARENT_IRQ; i++) { - parent_irq[i] =3D irq_of_parse_and_map(node, i); - if (parent_irq[i] <=3D 0) - break; - - priv->num_parents++; - } - - if (!priv->num_parents) { - pr_err("Failed to get parent irqs\n"); - err =3D -ENODEV; - goto iounmap_base; - } =20 - priv->htvec_domain =3D irq_domain_create_linear(of_node_to_fwnode(node), + /* Setup IRQ domain */ + priv->htvec_domain =3D irq_domain_create_linear(domain_handle, (VEC_COUNT_PER_REG * priv->num_parents), &htvec_domain_ops, priv); if (!priv->htvec_domain) { - pr_err("Failed to create IRQ domain\n"); - err =3D -ENOMEM; - goto irq_dispose; + pr_err("loongson-htvec: cannot add IRQ domain\n"); + goto iounmap_base; } =20 htvec_reset(priv); =20 - for (i =3D 0; i < priv->num_parents; i++) + for (i =3D 0; i < priv->num_parents; i++) { irq_set_chained_handler_and_data(parent_irq[i], htvec_irq_dispatch, priv); + } + + htvec_priv =3D priv; =20 return 0; =20 -irq_dispose: - for (; i > 0; i--) - irq_dispose_mapping(parent_irq[i - 1]); iounmap_base: iounmap(priv->base); -free_priv: kfree(priv); =20 - return err; + return -EINVAL; +} + +#ifdef CONFIG_OF + +static int htvec_of_init(struct device_node *node, + struct device_node *parent) +{ + int i, err; + int parent_irq[8]; + int num_parents =3D 0; + struct resource res; + + if (of_address_to_resource(node, 0, &res)) + return -EINVAL; + + /* Interrupt may come from any of the 8 interrupt lines */ + for (i =3D 0; i < HTVEC_MAX_PARENT_IRQ; i++) { + parent_irq[i] =3D irq_of_parse_and_map(node, i); + if (parent_irq[i] <=3D 0) + break; + + num_parents++; + } + + err =3D htvec_init(res.start, resource_size(&res), + num_parents, parent_irq, of_node_to_fwnode(node)); + if (err < 0) + return err; + + return 0; } =20 IRQCHIP_DECLARE(htvec, "loongson,htvec-1.0", htvec_of_init); + +#endif + +#ifdef CONFIG_ACPI +static int __init +pch_pic_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_bio_pic *pchpic_entry =3D (struct acpi_madt_bio_pic *)he= ader; + + return pch_pic_acpi_init(htvec_priv->htvec_domain, pchpic_entry); +} + +static int __init +pch_msi_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_msi_pic *pchmsi_entry =3D (struct acpi_madt_msi_pic *)he= ader; + + return pch_msi_acpi_init(htvec_priv->htvec_domain, pchmsi_entry); +} + +static int __init acpi_cascade_irqdomain_init(void) +{ + acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, + pch_pic_parse_madt, 0); + acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, + pch_msi_parse_madt, 0); + return 0; +} + +int __init htvec_acpi_init(struct irq_domain *parent, + struct acpi_madt_ht_pic *acpi_htvec) +{ + int i, ret; + int num_parents, parent_irq[8]; + struct fwnode_handle *domain_handle; + + if (!acpi_htvec) + return -EINVAL; + + num_parents =3D HTVEC_MAX_PARENT_IRQ; + + domain_handle =3D irq_domain_alloc_fwnode((phys_addr_t *)acpi_htvec); + if (!domain_handle) { + pr_err("Unable to allocate domain handle\n"); + return -ENOMEM; + } + + /* Interrupt may come from any of the 8 interrupt lines */ + for (i =3D 0; i < HTVEC_MAX_PARENT_IRQ; i++) + parent_irq[i] =3D irq_create_mapping(parent, acpi_htvec->cascade[i]); + + ret =3D htvec_init(acpi_htvec->address, acpi_htvec->size, + num_parents, parent_irq, domain_handle); + + if (!ret) + acpi_cascade_irqdomain_init(); + else + irq_domain_free_fwnode(domain_handle); + + return ret; +} + +#endif --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BB37BC433EF for ; Fri, 15 Jul 2022 07:11:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231499AbiGOHLk (ORCPT ); Fri, 15 Jul 2022 03:11:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230283AbiGOHLg (ORCPT ); Fri, 15 Jul 2022 03:11:36 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 614DC28710 for ; Fri, 15 Jul 2022 00:11:34 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S13; Fri, 15 Jul 2022 15:06:01 +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 V15 11/15] irqchip/loongson-liointc: Add ACPI init support Date: Fri, 15 Jul 2022 15:05:47 +0800 Message-Id: <1657868751-30444-12-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S13 X-Coremail-Antispam: 1UD129KBjvJXoW3KryDKry3KF13Zw13XFW5Jrb_yoWDtF18pF W8A34qqr45GFy7WrWktFn8Za4ayw45uFsrXFWruas7AFnrJ3sYyF1ruFnrAF43C3yrWFWa vF4rta18GF45Ca7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv01xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUb XdbUUUUUU== X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen LIOINTC stands for "Legacy I/O Interrupts" that described in Section 11.1 of "Loongson 3A5000 Processor Reference Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 4 +- arch/loongarch/kernel/irq.c | 1 - drivers/irqchip/irq-loongson-liointc.c | 225 ++++++++++++++++++++++-------= ---- 3 files changed, 152 insertions(+), 78 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index 8775dc6..b4c7956 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -97,7 +97,7 @@ static inline void eiointc_enable(void) =20 struct irq_domain *loongarch_cpu_irq_init(void); =20 -struct irq_domain *liointc_acpi_init(struct irq_domain *parent, +int liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc); struct irq_domain *eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc); @@ -122,7 +122,7 @@ int pch_pic_acpi_init(struct irq_domain *parent, extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS]; =20 extern struct irq_domain *cpu_domain; -extern struct irq_domain *liointc_domain; +extern struct fwnode_handle *liointc_handle; extern struct fwnode_handle *pch_lpc_handle; extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; =20 diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index ce21281..b04201c 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -26,7 +26,6 @@ EXPORT_PER_CPU_SYMBOL(irq_stat); =20 struct irq_domain *cpu_domain; -struct irq_domain *liointc_domain; =20 /* * 'what should we do if we get a hw irq event on an illegal vector'. diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-l= oongson-liointc.c index 8d05d8b..93eb01b 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -23,7 +23,7 @@ #endif =20 #define LIOINTC_CHIP_IRQ 32 -#define LIOINTC_NUM_PARENT 4 +#define LIOINTC_NUM_PARENT 4 #define LIOINTC_NUM_CORES 4 =20 #define LIOINTC_INTC_CHIP_START 0x20 @@ -41,6 +41,7 @@ =20 #if defined(CONFIG_MIPS) #define liointc_core_id get_ebase_cpunum() +#define GSI_MIN_CPU_IRQ 0 #else #define liointc_core_id get_csr_cpuid() #endif @@ -58,6 +59,8 @@ struct liointc_priv { bool has_lpc_irq_errata; }; =20 +struct fwnode_handle *liointc_handle; + static void liointc_chained_handle_irq(struct irq_desc *desc) { struct liointc_handler_data *handler =3D irq_desc_get_handler_data(desc); @@ -153,97 +156,79 @@ static void liointc_resume(struct irq_chip_generic *g= c) irq_gc_unlock_irqrestore(gc, flags); } =20 -static const char * const parent_names[] =3D {"int0", "int1", "int2", "int= 3"}; -static const char * const core_reg_names[] =3D {"isr0", "isr1", "isr2", "i= sr3"}; +static int parent_irq[LIOINTC_NUM_PARENT]; +static u32 parent_int_map[LIOINTC_NUM_PARENT]; +static const char *const parent_names[] =3D {"int0", "int1", "int2", "int3= "}; +static const char *const core_reg_names[] =3D {"isr0", "isr1", "isr2", "is= r3"}; =20 -static void __iomem *liointc_get_reg_byname(struct device_node *node, - const char *name) +static int liointc_domain_xlate(struct irq_domain *d, struct device_node *= ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) { - int index =3D of_property_match_string(node, "reg-names", name); - - if (index < 0) - return NULL; - - return of_iomap(node, index); + if (WARN_ON(intsize < 1)) + return -EINVAL; + *out_hwirq =3D intspec[0] - GSI_MIN_CPU_IRQ; + *out_type =3D IRQ_TYPE_NONE; + return 0; } =20 -static int __init liointc_of_init(struct device_node *node, - struct device_node *parent) +static const struct irq_domain_ops acpi_irq_gc_ops =3D { + .map =3D irq_map_generic_chip, + .unmap =3D irq_unmap_generic_chip, + .xlate =3D liointc_domain_xlate, +}; + +static int liointc_init(phys_addr_t addr, unsigned long size, int revision, + struct fwnode_handle *domain_handle, struct device_node *node) { + int i, err; + void __iomem *base; + struct irq_chip_type *ct; struct irq_chip_generic *gc; struct irq_domain *domain; - struct irq_chip_type *ct; struct liointc_priv *priv; - void __iomem *base; - u32 of_parent_int_map[LIOINTC_NUM_PARENT]; - int parent_irq[LIOINTC_NUM_PARENT]; - bool have_parent =3D FALSE; - int sz, i, err =3D 0; =20 priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; =20 - if (of_device_is_compatible(node, "loongson,liointc-2.0")) { - base =3D liointc_get_reg_byname(node, "main"); - if (!base) { - err =3D -ENODEV; - goto out_free_priv; - } + base =3D ioremap(addr, size); + if (!base) + goto out_free_priv; =20 - for (i =3D 0; i < LIOINTC_NUM_CORES; i++) - priv->core_isr[i] =3D liointc_get_reg_byname(node, core_reg_names[i]); - if (!priv->core_isr[0]) { - err =3D -ENODEV; - goto out_iounmap_base; - } - } else { - base =3D of_iomap(node, 0); - if (!base) { - err =3D -ENODEV; - goto out_free_priv; - } + for (i =3D 0; i < LIOINTC_NUM_CORES; i++) + priv->core_isr[i] =3D base + LIOINTC_REG_INTC_STATUS; =20 - for (i =3D 0; i < LIOINTC_NUM_CORES; i++) - priv->core_isr[i] =3D base + LIOINTC_REG_INTC_STATUS; - } + for (i =3D 0; i < LIOINTC_NUM_PARENT; i++) + priv->handler[i].parent_int_map =3D parent_int_map[i]; =20 - for (i =3D 0; i < LIOINTC_NUM_PARENT; i++) { - parent_irq[i] =3D of_irq_get_byname(node, parent_names[i]); - if (parent_irq[i] > 0) - have_parent =3D TRUE; - } - if (!have_parent) { - err =3D -ENODEV; - goto out_iounmap_isr; - } + if (revision > 1) { + for (i =3D 0; i < LIOINTC_NUM_CORES; i++) { + int index =3D of_property_match_string(node, + "reg-names", core_reg_names[i]); =20 - sz =3D of_property_read_variable_u32_array(node, - "loongson,parent_int_map", - &of_parent_int_map[0], - LIOINTC_NUM_PARENT, - LIOINTC_NUM_PARENT); - if (sz < 4) { - pr_err("loongson-liointc: No parent_int_map\n"); - err =3D -ENODEV; - goto out_iounmap_isr; - } + if (index < 0) + return -EINVAL; =20 - for (i =3D 0; i < LIOINTC_NUM_PARENT; i++) - priv->handler[i].parent_int_map =3D of_parent_int_map[i]; + priv->core_isr[i] =3D of_iomap(node, index); + } + } =20 /* Setup IRQ domain */ - domain =3D irq_domain_add_linear(node, 32, + if (!acpi_disabled) + domain =3D irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ, + &acpi_irq_gc_ops, priv); + else + domain =3D irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ, &irq_generic_chip_ops, priv); if (!domain) { pr_err("loongson-liointc: cannot add IRQ domain\n"); - err =3D -EINVAL; - goto out_iounmap_isr; + goto out_iounmap; } =20 - err =3D irq_alloc_domain_generic_chips(domain, 32, 1, - node->full_name, handle_level_irq, - IRQ_NOPROBE, 0, 0); + err =3D irq_alloc_domain_generic_chips(domain, LIOINTC_CHIP_IRQ, 1, + (node ? node->full_name : "LIOINTC"), + handle_level_irq, 0, IRQ_NOPROBE, 0); if (err) { pr_err("loongson-liointc: unable to register IRQ domain\n"); goto out_free_domain; @@ -299,24 +284,114 @@ static int __init liointc_of_init(struct device_node= *node, liointc_chained_handle_irq, &priv->handler[i]); } =20 + liointc_handle =3D domain_handle; return 0; =20 out_free_domain: irq_domain_remove(domain); -out_iounmap_isr: - for (i =3D 0; i < LIOINTC_NUM_CORES; i++) { - if (!priv->core_isr[i]) - continue; - iounmap(priv->core_isr[i]); - } -out_iounmap_base: +out_iounmap: iounmap(base); out_free_priv: kfree(priv); =20 - return err; + return -EINVAL; +} + +#ifdef CONFIG_OF + +static int __init liointc_of_init(struct device_node *node, + struct device_node *parent) +{ + bool have_parent =3D FALSE; + int sz, i, index, revision, err =3D 0; + struct resource res; + + if (!of_device_is_compatible(node, "loongson,liointc-2.0")) { + index =3D 0; + revision =3D 1; + } else { + index =3D of_property_match_string(node, "reg-names", "main"); + revision =3D 2; + } + + if (of_address_to_resource(node, index, &res)) + return -EINVAL; + + for (i =3D 0; i < LIOINTC_NUM_PARENT; i++) { + parent_irq[i] =3D of_irq_get_byname(node, parent_names[i]); + if (parent_irq[i] > 0) + have_parent =3D TRUE; + } + if (!have_parent) + return -ENODEV; + + sz =3D of_property_read_variable_u32_array(node, + "loongson,parent_int_map", + &parent_int_map[0], + LIOINTC_NUM_PARENT, + LIOINTC_NUM_PARENT); + if (sz < 4) { + pr_err("loongson-liointc: No parent_int_map\n"); + return -ENODEV; + } + + err =3D liointc_init(res.start, resource_size(&res), + revision, of_node_to_fwnode(node), node); + if (err < 0) + return err; + + return 0; } =20 IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_i= nit); IRQCHIP_DECLARE(loongson_liointc_1_0a, "loongson,liointc-1.0a", liointc_of= _init); IRQCHIP_DECLARE(loongson_liointc_2_0, "loongson,liointc-2.0", liointc_of_i= nit); + +#endif + +#ifdef CONFIG_ACPI +static int __init htintc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_ht_pic *htintc_entry =3D (struct acpi_madt_ht_pic *)head= er; + struct irq_domain *parent =3D irq_find_matching_fwnode(liointc_handle, DO= MAIN_BUS_ANY); + + return htvec_acpi_init(parent, htintc_entry); +} + +static int __init acpi_cascade_irqdomain_init(void) +{ + acpi_table_parse_madt(ACPI_MADT_TYPE_HT_PIC, + htintc_parse_madt, 0); + return 0; +} + +int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_l= io_pic *acpi_liointc) +{ + int ret; + struct fwnode_handle *domain_handle; + + if (!acpi_liointc) + return -EINVAL; + + parent_int_map[0] =3D acpi_liointc->cascade_map[0]; + parent_int_map[1] =3D acpi_liointc->cascade_map[1]; + + parent_irq[0] =3D irq_create_mapping(parent, acpi_liointc->cascade[0]); + parent_irq[1] =3D irq_create_mapping(parent, acpi_liointc->cascade[1]); + + domain_handle =3D irq_domain_alloc_fwnode((phys_addr_t *)acpi_liointc); + if (!domain_handle) { + pr_err("Unable to allocate domain handle\n"); + return -ENOMEM; + } + ret =3D liointc_init(acpi_liointc->address, acpi_liointc->size, + 1, domain_handle, NULL); + if (ret =3D=3D 0) + acpi_cascade_irqdomain_init(); + else + irq_domain_free_fwnode(domain_handle); + + return ret; +} +#endif --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 31DDDC433EF for ; Fri, 15 Jul 2022 07:07:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231748AbiGOHHI (ORCPT ); Fri, 15 Jul 2022 03:07:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231441AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B97DB73919 for ; Fri, 15 Jul 2022 00:06:08 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S14; Fri, 15 Jul 2022 15:06:02 +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 V15 12/15] LoongArch: prepare to support multiple pch-pic and pch-msi irqdomain Date: Fri, 15 Jul 2022 15:05:48 +0800 Message-Id: <1657868751-30444-13-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S14 X-Coremail-Antispam: 1UD129KBjvJXoWxJw4Duw18AF4fXr4rGw13CFg_yoW5ZF1rpF 9xu3Z8tr45GryxWryfta15Wr4rGas7Ca12qa13Ca43Kr1xWryvqF4vyr9ruFy5ta1rAa4I qa13tFW5ur4DA37anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvF1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v2 6r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvj fUoOJ5UUUUU X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" For systems with two chipsets, there are two related pch-pic and pch-msi irqdomains, each of which has the same node id as its parent irqdomain. So we use a structure to mantain the relation of node and it's parent irqdomain as pch irqdomin, the 'pci_segment' field is only used to match the pci segment of a pci device when setting msi irqdomain for the device. struct acpi_vector_group { int node; int pci_segment; struct irq_domain *parent; }; The field 'pci_segment' and 'node' are initialized from MCFG, and the parent irqdomain driver will set field 'parent' by matching same 'node'. Signed-off-by: Jianmin Lv --- arch/loongarch/include/asm/irq.h | 8 ++++++++ arch/loongarch/kernel/irq.c | 38 ++++++++++++++++++++++++++++++++++++= ++ 2 files changed, 46 insertions(+) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index b4c7956..a07315a 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -48,6 +48,14 @@ static inline bool on_irq_stack(int cpu, unsigned long s= p) #define MAX_IO_PICS 2 #define NR_IRQS (64 + (256 * MAX_IO_PICS)) =20 +struct acpi_vector_group { + int node; + int pci_segment; + struct irq_domain *parent; +}; +extern struct acpi_vector_group pch_group[MAX_IO_PICS]; +extern struct acpi_vector_group msi_group[MAX_IO_PICS]; + #define CORES_PER_EIO_NODE 4 =20 #define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */ diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index b04201c..06f2a15 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -26,6 +26,8 @@ EXPORT_PER_CPU_SYMBOL(irq_stat); =20 struct irq_domain *cpu_domain; +struct acpi_vector_group pch_group[MAX_IO_PICS]; +struct acpi_vector_group msi_group[MAX_IO_PICS]; =20 /* * 'what should we do if we get a hw irq event on an illegal vector'. @@ -52,6 +54,41 @@ int arch_show_interrupts(struct seq_file *p, int prec) return 0; } =20 +static int __init early_pci_mcfg_parse(struct acpi_table_header *header) +{ + struct acpi_table_mcfg *mcfg; + struct acpi_mcfg_allocation *mptr; + int i, n; + + if (header->length < sizeof(struct acpi_table_mcfg)) + return -EINVAL; + + n =3D (header->length - sizeof(struct acpi_table_mcfg)) / + sizeof(struct acpi_mcfg_allocation); + mcfg =3D (struct acpi_table_mcfg *)header; + mptr =3D (struct acpi_mcfg_allocation *) &mcfg[1]; + + for (i =3D 0; i < n; i++, mptr++) { + msi_group[i].pci_segment =3D mptr->pci_segment; + pch_group[i].node =3D msi_group[i].node =3D (mptr->address >> 44) & 0xf; + } + + return 0; +} + +static void __init init_vec_parent_group(void) +{ + int i; + + for (i =3D 0; i < MAX_IO_PICS; i++) { + msi_group[i].pci_segment =3D -1; + msi_group[i].node =3D -1; + pch_group[i].node =3D -1; + } + + acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); +} + void __init init_IRQ(void) { int i; @@ -65,6 +102,7 @@ void __init init_IRQ(void) clear_csr_ecfg(ECFG0_IM); clear_csr_estat(ESTATF_IP); =20 + init_vec_parent_group(); irqchip_init(); #ifdef CONFIG_SMP ipi_irq =3D EXCCODE_IPI - EXCCODE_INT_START; --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA4CAC43334 for ; Fri, 15 Jul 2022 07:07:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231970AbiGOHH2 (ORCPT ); Fri, 15 Jul 2022 03:07:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41292 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231648AbiGOHGR (ORCPT ); Fri, 15 Jul 2022 03:06:17 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8B38074359 for ; Fri, 15 Jul 2022 00:06:10 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S15; Fri, 15 Jul 2022 15:06:02 +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 V15 13/15] irqchip: Add Loongson Extended I/O interrupt controller support Date: Fri, 15 Jul 2022 15:05:49 +0800 Message-Id: <1657868751-30444-14-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S15 X-Coremail-Antispam: 1UD129KBjvAXoW3uw1DJw4UCry5tr1fXr18Xwb_yoW8XF15Wo WfJFsxtw1rJr1fZrWrWw4xtry5Zas0qr9Yywn3urZ3u3WfAa15KF47W3Waya13Ja1rCryx Za4xXa4xJFWxXFn8n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUY47CY07I20VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAF z4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0Y4vE2Ix0cI 8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwA2z4x0Y4vE x4A2jsIE14v26F4UJVW0owA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1le2I262IYc4 CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_ Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x 0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc2xSY4AK6svPMxAIw28IcxkI7VAKI48J MxAIw28IcVCjz48v1sIEY20_XrWUJr1UMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I 8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8 ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8IcVCY1x 0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AK xVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa 7VUbXdbUUUUUU== X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Huacai Chen EIOINTC stands for "Extended I/O Interrupts" that described in Section 11.2 of "Loongson 3A5000 Processor Reference Manual". For more information please refer Documentation/loongarch/irq-chip-model.rst. Loongson-3A5000 has 4 cores per NUMA node, and each NUMA node has an EIOINTC; while Loongson-3C5000 has 16 cores per NUMA node, and each NUMA node has 4 EIOINTCs. In other words, 16 cores of one NUMA node in Loongson-3C5000 are organized in 4 groups, each group connects to an EIOINTC. We call the "group" here as an EIOINTC node, so each EIOINTC node always includes 4 cores (both in Loongson-3A5000 and Loongson- 3C5000). Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/irq.h | 11 +- drivers/irqchip/Kconfig | 10 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-loongson-eiointc.c | 395 +++++++++++++++++++++++++++++= ++++ include/linux/cpuhotplug.h | 1 + 5 files changed, 408 insertions(+), 10 deletions(-) create mode 100644 drivers/irqchip/irq-loongson-eiointc.c diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/= irq.h index a07315a..a826ac4 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -87,15 +87,6 @@ struct acpi_vector_group { extern int find_pch_pic(u32 gsi); extern int eiointc_get_node(int id); =20 -static inline void eiointc_enable(void) -{ - uint64_t misc; - - misc =3D iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC); - misc |=3D IOCSR_MISC_FUNC_EXT_IOI_EN; - iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC); -} - struct acpi_madt_lio_pic; struct acpi_madt_eio_pic; struct acpi_madt_ht_pic; @@ -107,7 +98,7 @@ static inline void eiointc_enable(void) =20 int liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc); -struct irq_domain *eiointc_acpi_init(struct irq_domain *parent, +int eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc); =20 int htvec_acpi_init(struct irq_domain *parent, diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 8844e6b..8f077d3 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -555,6 +555,16 @@ config LOONGSON_LIOINTC help Support for the Loongson Local I/O Interrupt Controller. =20 +config LOONGSON_EIOINTC + bool "Loongson Extend I/O Interrupt Controller" + depends on LOONGARCH + depends on MACH_LOONGSON64 + default MACH_LOONGSON64 + select IRQ_DOMAIN_HIERARCHY + select GENERIC_IRQ_CHIP + help + Support for the Loongson3 Extend I/O Interrupt Vector Controller. + config LOONGSON_HTPIC bool "Loongson3 HyperTransport PIC Controller" depends on MACH_LOONGSON64 && MIPS diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 242b8b3..0cfd4f0 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) +=3D irq-ti-sci-intr.o obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) +=3D irq-ti-sci-inta.o obj-$(CONFIG_TI_PRUSS_INTC) +=3D irq-pruss-intc.o obj-$(CONFIG_LOONGSON_LIOINTC) +=3D irq-loongson-liointc.o +obj-$(CONFIG_LOONGSON_EIOINTC) +=3D irq-loongson-eiointc.o obj-$(CONFIG_LOONGSON_HTPIC) +=3D irq-loongson-htpic.o obj-$(CONFIG_LOONGSON_HTVEC) +=3D irq-loongson-htvec.o obj-$(CONFIG_LOONGSON_PCH_PIC) +=3D irq-loongson-pch-pic.o diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-l= oongson-eiointc.c new file mode 100644 index 0000000..80d8ca6 --- /dev/null +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Loongson Extend I/O Interrupt Controller support + * + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited + */ + +#define pr_fmt(fmt) "eiointc: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EIOINTC_REG_NODEMAP 0x14a0 +#define EIOINTC_REG_IPMAP 0x14c0 +#define EIOINTC_REG_ENABLE 0x1600 +#define EIOINTC_REG_BOUNCE 0x1680 +#define EIOINTC_REG_ISR 0x1800 +#define EIOINTC_REG_ROUTE 0x1c00 + +#define VEC_REG_COUNT 4 +#define VEC_COUNT_PER_REG 64 +#define VEC_COUNT (VEC_REG_COUNT * VEC_COUNT_PER_REG) +#define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) +#define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) +#define EIOINTC_ALL_ENABLE 0xffffffff + +#define MAX_EIO_NODES (NR_CPUS / CORES_PER_EIO_NODE) + +static int nr_pics; + +struct eiointc_priv { + u32 node; + nodemask_t node_map; + cpumask_t cpuspan_map; + struct fwnode_handle *domain_handle; + struct irq_domain *eiointc_domain; +}; + +static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; + +static void eiointc_enable(void) +{ + uint64_t misc; + + misc =3D iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC); + misc |=3D IOCSR_MISC_FUNC_EXT_IOI_EN; + iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC); +} + +static int cpu_to_eio_node(int cpu) +{ + return cpu_logical_map(cpu) / CORES_PER_EIO_NODE; +} + +static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int = mnode, nodemask_t *node_map) +{ + int i, node, cpu_node, route_node; + unsigned char coremap; + uint32_t pos_off, data, data_byte, data_mask; + + pos_off =3D pos & ~3; + data_byte =3D pos & 3; + data_mask =3D ~BIT_MASK(data_byte) & 0xf; + + /* Calculate node and coremap of target irq */ + cpu_node =3D cpu_logical_map(cpu) / CORES_PER_EIO_NODE; + coremap =3D BIT(cpu_logical_map(cpu) % CORES_PER_EIO_NODE); + + for_each_online_cpu(i) { + node =3D cpu_to_eio_node(i); + if (!node_isset(node, *node_map)) + continue; + + /* EIO node 0 is in charge of inter-node interrupt dispatch */ + route_node =3D (node =3D=3D mnode) ? cpu_node : node; + data =3D ((coremap | (route_node << 4)) << (data_byte * 8)); + csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, node * CORES_= PER_EIO_NODE); + } +} + +static DEFINE_RAW_SPINLOCK(affinity_lock); + +static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpuma= sk *affinity, bool force) +{ + unsigned int cpu; + unsigned long flags; + uint32_t vector, regaddr; + struct cpumask intersect_affinity; + struct eiointc_priv *priv =3D d->domain->host_data; + + raw_spin_lock_irqsave(&affinity_lock, flags); + + cpumask_and(&intersect_affinity, affinity, cpu_online_mask); + cpumask_and(&intersect_affinity, &intersect_affinity, &priv->cpuspan_map); + + if (cpumask_empty(&intersect_affinity)) { + raw_spin_unlock_irqrestore(&affinity_lock, flags); + return -EINVAL; + } + cpu =3D cpumask_first(&intersect_affinity); + + vector =3D d->hwirq; + regaddr =3D EIOINTC_REG_ENABLE + ((vector >> 5) << 2); + + /* Mask target vector */ + csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), 0x0, 0); + /* Set route for target vector */ + eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map); + /* Unmask target vector */ + csr_any_send(regaddr, EIOINTC_ALL_ENABLE, 0x0, 0); + + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + + raw_spin_unlock_irqrestore(&affinity_lock, flags); + + return IRQ_SET_MASK_OK; +} + +static int eiointc_index(int node) +{ + int i; + + for (i =3D 0; i < nr_pics; i++) { + if (node_isset(node, eiointc_priv[i]->node_map)) + return i; + } + + return -1; +} + +static int eiointc_router_init(unsigned int cpu) +{ + int i, bit; + uint32_t data; + uint32_t node =3D cpu_to_eio_node(cpu); + uint32_t index =3D eiointc_index(node); + + if (index < 0) { + pr_err("Error: invalid nodemap!\n"); + return -1; + } + + if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) =3D=3D 0) { + eiointc_enable(); + + for (i =3D 0; i < VEC_COUNT / 32; i++) { + data =3D (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2))); + iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4); + } + + for (i =3D 0; i < VEC_COUNT / 32 / 4; i++) { + bit =3D BIT(1 + index); /* Route to IP[1 + index] */ + data =3D bit | (bit << 8) | (bit << 16) | (bit << 24); + iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); + } + + for (i =3D 0; i < VEC_COUNT / 4; i++) { + /* Route to Node-0 Core-0 */ + if (index =3D=3D 0) + bit =3D BIT(cpu_logical_map(0)); + else + bit =3D (eiointc_priv[index]->node << 4) | 1; + + data =3D bit | (bit << 8) | (bit << 16) | (bit << 24); + iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); + } + + for (i =3D 0; i < VEC_COUNT / 32; i++) { + data =3D 0xffffffff; + iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); + iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); + } + } + + return 0; +} + +static void eiointc_irq_dispatch(struct irq_desc *desc) +{ + int i; + u64 pending; + bool handled =3D false; + struct irq_chip *chip =3D irq_desc_get_chip(desc); + struct eiointc_priv *priv =3D irq_desc_get_handler_data(desc); + + chained_irq_enter(chip, desc); + + for (i =3D 0; i < VEC_REG_COUNT; i++) { + pending =3D iocsr_read64(EIOINTC_REG_ISR + (i << 3)); + iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3)); + while (pending) { + int bit =3D __ffs(pending); + int irq =3D bit + VEC_COUNT_PER_REG * i; + + generic_handle_domain_irq(priv->eiointc_domain, irq); + pending &=3D ~BIT(bit); + handled =3D true; + } + } + + if (!handled) + spurious_interrupt(); + + chained_irq_exit(chip, desc); +} + +static void eiointc_ack_irq(struct irq_data *d) +{ +} + +static void eiointc_mask_irq(struct irq_data *d) +{ +} + +static void eiointc_unmask_irq(struct irq_data *d) +{ +} + +static struct irq_chip eiointc_irq_chip =3D { + .name =3D "EIOINTC", + .irq_ack =3D eiointc_ack_irq, + .irq_mask =3D eiointc_mask_irq, + .irq_unmask =3D eiointc_unmask_irq, + .irq_set_affinity =3D eiointc_set_irq_affinity, +}; + +static int eiointc_domain_alloc(struct irq_domain *domain, unsigned int vi= rq, + unsigned int nr_irqs, void *arg) +{ + int ret; + unsigned int i, type; + unsigned long hwirq =3D 0; + struct eiointc *priv =3D domain->host_data; + + ret =3D irq_domain_translate_onecell(domain, arg, &hwirq, &type); + if (ret) + return ret; + + for (i =3D 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip, + priv, handle_edge_irq, NULL, NULL); + } + + return 0; +} + +static void eiointc_domain_free(struct irq_domain *domain, unsigned int vi= rq, + unsigned int nr_irqs) +{ + int i; + + for (i =3D 0; i < nr_irqs; i++) { + struct irq_data *d =3D irq_domain_get_irq_data(domain, virq + i); + + irq_set_handler(virq + i, NULL); + irq_domain_reset_irq_data(d); + } +} + +static const struct irq_domain_ops eiointc_domain_ops =3D { + .translate =3D irq_domain_translate_onecell, + .alloc =3D eiointc_domain_alloc, + .free =3D eiointc_domain_free, +}; + +static void acpi_set_vec_parent(int node, struct irq_domain *parent, struc= t acpi_vector_group *vec_group) +{ + int i; + + if (cpu_has_flatmode) + node =3D cpu_to_node(node * CORES_PER_EIO_NODE); + + for (i =3D 0; i < MAX_IO_PICS; i++) { + if (node =3D=3D vec_group[i].node) { + vec_group[i].parent =3D parent; + return; + } + } +} + +struct irq_domain *acpi_get_vec_parent(int node, struct acpi_vector_group = *vec_group) +{ + int i; + + for (i =3D 0; i < MAX_IO_PICS; i++) { + if (node =3D=3D vec_group[i].node) + return vec_group[i].parent; + } + return NULL; +} + +static int __init +pch_pic_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_bio_pic *pchpic_entry =3D (struct acpi_madt_bio_pic *)he= ader; + unsigned int node =3D (pchpic_entry->address >> 44) & 0xf; + struct irq_domain *parent =3D acpi_get_vec_parent(node, pch_group); + + if (parent) + return pch_pic_acpi_init(parent, pchpic_entry); + + return -EINVAL; +} + +static int __init +pch_msi_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_msi_pic *pchmsi_entry =3D (struct acpi_madt_msi_pic *)he= ader; + struct irq_domain *parent =3D acpi_get_vec_parent(eiointc_priv[nr_pics - = 1]->node, msi_group); + + if (parent) + return pch_msi_acpi_init(parent, pchmsi_entry); + + return -EINVAL; +} + +static int __init acpi_cascade_irqdomain_init(void) +{ + acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, + pch_pic_parse_madt, 0); + acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, + pch_msi_parse_madt, 1); + return 0; +} + +int __init eiointc_acpi_init(struct irq_domain *parent, + struct acpi_madt_eio_pic *acpi_eiointc) +{ + int i, parent_irq; + unsigned long node_map; + struct eiointc_priv *priv; + + priv =3D kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->domain_handle =3D irq_domain_alloc_fwnode((phys_addr_t *)acpi_eioin= tc); + if (!priv->domain_handle) { + pr_err("Unable to allocate domain handle\n"); + goto out_free_priv; + } + + priv->node =3D acpi_eiointc->node; + node_map =3D acpi_eiointc->node_map ? : -1ULL; + + for_each_possible_cpu(i) { + if (node_map & (1ULL << cpu_to_eio_node(i))) { + node_set(cpu_to_eio_node(i), priv->node_map); + cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i)); + } + } + + /* Setup IRQ domain */ + priv->eiointc_domain =3D irq_domain_create_linear(priv->domain_handle, VE= C_COUNT, + &eiointc_domain_ops, priv); + if (!priv->eiointc_domain) { + pr_err("loongson-eiointc: cannot add IRQ domain\n"); + goto out_free_handle; + } + + eiointc_priv[nr_pics++] =3D priv; + + eiointc_router_init(0); + + parent_irq =3D irq_create_mapping(parent, acpi_eiointc->cascade); + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); + + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, + "irqchip/loongarch/intc:starting", + eiointc_router_init, NULL); + + acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); + acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); + acpi_cascade_irqdomain_init(); + + return 0; + +out_free_handle: + irq_domain_free_fwnode(priv->domain_handle); + priv->domain_handle =3D NULL; +out_free_priv: + kfree(priv); + + return -ENOMEM; +} diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 19f0dbf..de662f3 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -151,6 +151,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_BCM2836_STARTING, CPUHP_AP_IRQ_MIPS_GIC_STARTING, CPUHP_AP_IRQ_RISCV_STARTING, + CPUHP_AP_IRQ_LOONGARCH_STARTING, CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, CPUHP_AP_ARM_MVEBU_COHERENCY, CPUHP_AP_MICROCODE_LOADER, --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40A3DC433EF for ; Fri, 15 Jul 2022 07:07:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231953AbiGOHHW (ORCPT ); Fri, 15 Jul 2022 03:07:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41208 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230505AbiGOHGR (ORCPT ); Fri, 15 Jul 2022 03:06:17 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8B04174358 for ; Fri, 15 Jul 2022 00:06:10 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S16; Fri, 15 Jul 2022 15:06:03 +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 V15 14/15] irqchip: Add LoongArch CPU interrupt controller support Date: Fri, 15 Jul 2022 15:05:50 +0800 Message-Id: <1657868751-30444-15-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S16 X-Coremail-Antispam: 1UD129KBjvJXoW3WFyftFW7GrykZr18Xw4fKrg_yoWftw1DpF W3AwsFqr4UJFW8Xr9Yka98Wry3Zw1fG3y2qayfGa43Ar4DtryqqF1vyr9F9FyYy3y8Gay2 vF4rtFW8uF4UAa7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvF1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v2 6r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvj fUoOJ5UUUUU X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 | 8 +-- arch/loongarch/kernel/irq.c | 15 ++++- arch/loongarch/kernel/time.c | 14 ++++- drivers/irqchip/Kconfig | 10 +++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-loongarch-cpu.c | 119 ++++++++++++++++++++++++++++++++= ++++ 6 files changed, 157 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 a826ac4..ca46856 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 <=3D sp && sp <=3D high); } =20 -int get_ipi_irq(void); -int get_pmc_irq(void); -int get_timer_irq(void); void spurious_interrupt(void); =20 #define NR_IRQS_LEGACY 16 @@ -94,13 +91,10 @@ struct acpi_vector_group { struct acpi_madt_msi_pic; struct acpi_madt_lpc_pic; =20 -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, struct acpi_madt_eio_pic *acpi_eiointc); - int htvec_acpi_init(struct irq_domain *parent, struct acpi_madt_ht_pic *acpi_htvec); int pch_lpc_acpi_init(struct irq_domain *parent, @@ -120,7 +114,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]; =20 -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 06f2a15..99924d8 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -25,7 +25,6 @@ DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); EXPORT_PER_CPU_SYMBOL(irq_stat); =20 -struct irq_domain *cpu_domain; struct acpi_vector_group pch_group[MAX_IO_PICS]; struct acpi_vector_group msi_group[MAX_IO_PICS]; =20 @@ -89,6 +88,16 @@ static void __init init_vec_parent_group(void) acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); } =20 +static int __init get_ipi_irq(void) +{ + struct irq_domain *d =3D 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 +114,9 @@ void __init init_IRQ(void) init_vec_parent_group(); irqchip_init(); #ifdef CONFIG_SMP - ipi_irq =3D EXCCODE_IPI - EXCCODE_INT_START; + ipi_irq =3D get_ipi_irq(); + if (ipi_irq < 0) + panic("IPI IRQ mapping failed\n"); irq_set_percpu_devid(ipi_irq); r =3D request_percpu_irq(ipi_irq, loongson3_ipi_interrupt, "IPI", &ipi_du= mmy_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); } =20 +static int get_timer_irq(void) +{ + struct irq_domain *d =3D 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 =3D 0; =20 - irq =3D EXCCODE_TIMER - EXCCODE_INT_START; + irq =3D get_timer_irq(); + if (irq < 0) + pr_err("Failed to map irq %d (timer)\n", irq); =20 cd =3D &per_cpu(constant_clockevent_device, cpu); =20 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. =20 +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) +=3D irq-ls1x.o obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) +=3D irq-ti-sci-intr.o obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) +=3D irq-ti-sci-inta.o obj-$(CONFIG_TI_PRUSS_INTC) +=3D irq-pruss-intc.o +obj-$(CONFIG_IRQ_LOONGARCH_CPU) +=3D irq-loongarch-cpu.o obj-$(CONFIG_LOONGSON_LIOINTC) +=3D irq-loongson-liointc.o obj-$(CONFIG_LOONGSON_EIOINTC) +=3D irq-loongson-eiointc.o obj-$(CONFIG_LOONGSON_HTPIC) +=3D irq-loongson-htpic.o diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loon= garch-cpu.c new file mode 100644 index 0000000..476f407 --- /dev/null +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -0,0 +1,119 @@ +// 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 =3D { + .name =3D "CPUINTC", + .irq_mask =3D mask_loongarch_irq, + .irq_unmask =3D unmask_loongarch_irq, +}; + +static void handle_cpu_irq(struct pt_regs *regs) +{ + int hwirq; + unsigned int estat =3D read_csr_estat() & CSR_ESTAT_IS; + + while ((hwirq =3D ffs(estat))) { + estat &=3D ~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 =3D { + .map =3D loongarch_cpu_intc_map, + .xlate =3D irq_domain_xlate_onecell, +}; + +static int __init loongarch_cpu_irq_init(void) +{ + /* Mask interrupts. */ + clear_csr_ecfg(ECFG0_IM); + clear_csr_estat(ESTATF_IP); + + cpuintc_handle =3D irq_domain_alloc_fwnode(NULL); + irq_domain =3D 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); + + return 0; +} + +static int __init +liointc_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_lio_pic *liointc_entry =3D (struct acpi_madt_lio_pic *)h= eader; + + 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 =3D (struct acpi_madt_eio_pic *)h= eader; + + 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 coreintc_acpi_init_v1(union acpi_subtable_headers *heade= r, + const unsigned long end) +{ + if (irq_domain) + return 0; + + loongarch_cpu_irq_init(); + acpi_cascade_irqdomain_init(); + + return 0; +} + +IRQCHIP_ACPI_DECLARE(coreintc_v1, ACPI_MADT_TYPE_CORE_PIC, + NULL, ACPI_MADT_CORE_PIC_VERSION_V1, + coreintc_acpi_init_v1); --=20 1.8.3.1 From nobody Sat Apr 18 09:24:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC295C433EF for ; Fri, 15 Jul 2022 07:07:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231941AbiGOHHS (ORCPT ); Fri, 15 Jul 2022 03:07:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231579AbiGOHGP (ORCPT ); Fri, 15 Jul 2022 03:06:15 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E7E727393B for ; Fri, 15 Jul 2022 00:06:09 -0700 (PDT) Received: from localhost.localdomain.localdomain (unknown [10.2.5.46]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9AxWeDQEdFiyyogAA--.1717S17; Fri, 15 Jul 2022 15:06:03 +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 V15 15/15] irqchip / ACPI: Introduce ACPI_IRQ_MODEL_LPIC for LoongArch Date: Fri, 15 Jul 2022 15:05:51 +0800 Message-Id: <1657868751-30444-16-git-send-email-lvjianmin@loongson.cn> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> References: <1657868751-30444-1-git-send-email-lvjianmin@loongson.cn> X-CM-TRANSID: AQAAf9AxWeDQEdFiyyogAA--.1717S17 X-Coremail-Antispam: 1UD129KBjvJXoWxuF1rZryUXr1fJrW8tFWkZwb_yoW5AF1xpF WqgF15Ar48Kay7W3sxCa1Dury3uFyrGrW2qayfG347Cw4kGrykWF1kZF9FvFZ8A3y5Wa17 uF1DXFs8W3WUZrUanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUvF1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l1IIY67AE w4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2 IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UM28EF7xvwVC2 z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS0I0E0xvYzx vE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU JVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE-syl42xK82IYc2Ij64vIr41l 42xK82IY6x8ErcxFaVAv8VW5Wr1UJr1l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4 xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43 MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I 0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v2 6r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvj fUoOJ5UUUUU X-CM-SenderInfo: 5oymxthqpl0qxorr0wxvrqhubq/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" For LoongArch, ACPI_IRQ_MODEL_LPIC is introduced, and then the callback acpi_get_gsi_domain_id and acpi_gsi_to_irq_fallback are implemented. The acpi_get_gsi_domain_id callback returns related fwnode handle of irqdomain for different GSI range. The acpi_gsi_to_irq_fallback will create new mapping for gsi when the mapping of it is not found. Signed-off-by: Jianmin Lv --- drivers/acpi/bus.c | 3 +++ drivers/irqchip/irq-loongarch-cpu.c | 38 +++++++++++++++++++++++++++++++++= ++++ include/linux/acpi.h | 1 + 3 files changed, 42 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 86fa61a..63fbf00 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1145,6 +1145,9 @@ static int __init acpi_bus_init_irq(void) case ACPI_IRQ_MODEL_PLATFORM: message =3D "platform specific model"; break; + case ACPI_IRQ_MODEL_LPIC: + message =3D "LPIC"; + break; default: pr_info("Unknown interrupt routing model\n"); return -ENODEV; diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loon= garch-cpu.c index 476f407..93a4b15 100644 --- a/drivers/irqchip/irq-loongarch-cpu.c +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -16,6 +16,42 @@ static struct irq_domain *irq_domain; struct fwnode_handle *cpuintc_handle; =20 +static u32 lpic_gsi_to_irq(u32 gsi) +{ + /* Only pch irqdomain transferring is required for LoongArch. */ + if (gsi >=3D GSI_MIN_PCH_IRQ && gsi <=3D GSI_MAX_PCH_IRQ) + return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HI= GH); + + return 0; +} + +static struct fwnode_handle *lpic_get_gsi_domain_id(u32 gsi) +{ + int id; + struct fwnode_handle *domain_handle =3D NULL; + + switch (gsi) { + case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ: + if (liointc_handle) + domain_handle =3D liointc_handle; + break; + + case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ: + if (pch_lpc_handle) + domain_handle =3D pch_lpc_handle; + break; + + case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ: + id =3D find_pch_pic(gsi); + if (id >=3D 0 && pch_pic_handle[id]) + domain_handle =3D pch_pic_handle[id]; + + break; + } + + return domain_handle; +} + static void mask_loongarch_irq(struct irq_data *d) { clear_csr_ecfg(ECFGF(d->hwirq)); @@ -71,6 +107,8 @@ static int __init loongarch_cpu_irq_init(void) panic("Failed to add irqdomain for LoongArch CPU"); =20 set_handle_irq(&handle_cpu_irq); + acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id); + acpi_set_gsi_to_irq_fallback(lpic_gsi_to_irq); =20 return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index e2b60d5..76520f3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -105,6 +105,7 @@ enum acpi_irq_model_id { ACPI_IRQ_MODEL_IOSAPIC, ACPI_IRQ_MODEL_PLATFORM, ACPI_IRQ_MODEL_GIC, + ACPI_IRQ_MODEL_LPIC, ACPI_IRQ_MODEL_COUNT }; =20 --=20 1.8.3.1