From patchwork Thu Aug 3 17:59:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sunil V L X-Patchwork-Id: 13340420 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 56A2DC001DB for ; Thu, 3 Aug 2023 18:02:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=6Y0+/8D8jTwRIkUTedASMVTlNJBzFIzq0fhunjFdiM4=; b=z0yYpUwyl4mjJr AGwe83Ss8uYgS+KYqzryOFmlPXiyGHCbqK4k+Peb6LhvHPgxYT8mQgm/e9W9yi/1XaeD1+VBlkRVO ZqmPHN/UImNxbkjRpWIFO6m+PJbolrNQ/eQtTImFmxKvb/bmjn0iHyR6I+4/d/YYQXewSc187pj/b WhXxgB611p1XYSBW0CyBp3GhcoMjK/x5FxTmNejqP4QieNgjHuGY74ySC+R53WaKGuDvO7iG67s/F ZpssI3sQ8UmVkih6NqDOiiKwkJxiqcIj1N80jUbGJtzTnJyfs7Ue6hqM+mM4gxnovW5W3EwHrJtb8 BzXYiHEWWPj83cFSYfgw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qRcdu-00AVwo-2l; Thu, 03 Aug 2023 18:01:46 +0000 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qRcdq-00AVsI-2A for linux-arm-kernel@lists.infradead.org; Thu, 03 Aug 2023 18:01:45 +0000 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-686b643df5dso901741b3a.1 for ; Thu, 03 Aug 2023 11:01:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1691085702; x=1691690502; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MqlDPHKEWaBxTYs/0M8htriIKOWDT6nuJRMhsrHXzuE=; b=Mck7EqqRTTHdMEBXbHLoZwfOLdXJUnVodFv/es6odb8/Qq21nUhzlxmcrCQpHegUV1 qKWa65jRjHgYqT8ANyBw+GVASKqCOwBtVtvNwTQ9NuaGjcZ06UVpzTbD4zoHTAFAiZAq bC+kKVzDGdpGns7pLFPMO4CYn2tXf14kK4mXYgydh1+8YK5+ZpXO+dgkvzgwmGncgRDC EBqiRVaPJMAiim+QopcXM5/33h+EYYtGMCn9nVz286lZO7qUY51KfF5NwHxIJsTOYCRL nNpgZRPcRYp3J92EJNQFHRsHz+vYpZwdP4h6z60CpUAwZ3rmeewQu9jN+Ugw4weQY+0J wUTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691085702; x=1691690502; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MqlDPHKEWaBxTYs/0M8htriIKOWDT6nuJRMhsrHXzuE=; b=dlTowvan5PbeRG2JycLvOndJaTxPbIoH3VO/GUWvEqq9VN8tbpz9kOw8oMR09BvL99 l9ivDs2nNMY7lJFITRWvc2S+Fs3jlXImz2orWl1Y4UJSvkUCvYni/YzhelY07SxK/mrZ p8DAdXG2J7H5a9jP72LB1YhdfqZvVNwnyPTHc1Bfn5hRh8OpPO2p3Jn5CHnR9ATMIk3s T84aHWllXxXuZ39Jr6N757mmeVxdnRGIuqnZZ5LJHeS+GYqE2ayRhz909+UX+KticGBu NxB6LDXU3RXP+jou+5FdMBN2uYQVH1NVg7LwYLTU4THgdYqMZOeZsXcNCdvUJLwYYjcz antw== X-Gm-Message-State: ABy/qLa+JNpzzCm9RZY/4M7VWvFq83N6E7eaAHh/qpmnd+6oo16b60Ph rDuSawwNHjSPNl2P7HLqoFrDtw== X-Google-Smtp-Source: APBJJlEpOrcULPp+uHqf2SkiWQTzFmTJeS1yI+fASG26f/nZjZ0ASal13fAyFeapUfbB4CtpRCGyhA== X-Received: by 2002:a05:6a21:3b44:b0:130:9638:36d4 with SMTP id zy4-20020a056a213b4400b00130963836d4mr15110479pzb.33.1691085701012; Thu, 03 Aug 2023 11:01:41 -0700 (PDT) Received: from sunil-pc.Dlink ([106.51.190.143]) by smtp.gmail.com with ESMTPSA id s8-20020aa78d48000000b0065a1b05193asm134952pfe.185.2023.08.03.11.01.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Aug 2023 11:01:40 -0700 (PDT) From: Sunil V L To: linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org Cc: Jonathan Corbet , Paul Walmsley , Palmer Dabbelt , Albert Ou , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , Greg Kroah-Hartman , Daniel Lezcano , Thomas Gleixner , Anup Patel , Marc Zyngier , Bjorn Helgaas , Robert Moore , Haibo Xu , Andrew Jones , Conor Dooley , Atish Kumar Patra , Sunil V L Subject: [RFC PATCH v1 17/21] ACPI: RISC-V: Create APLIC platform device Date: Thu, 3 Aug 2023 23:29:12 +0530 Message-Id: <20230803175916.3174453-18-sunilvl@ventanamicro.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230803175916.3174453-1-sunilvl@ventanamicro.com> References: <20230803175916.3174453-1-sunilvl@ventanamicro.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230803_110142_826391_7FCF658B X-CRM114-Status: GOOD ( 23.03 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Since APLIC needs to be a platform device, probe the MADT and create platform devices for each APLIC in the system. Use software node framework for the fwnode which allows to create properties and hence the actual irqchip driver doesn't need to do anything different for ACPI vs DT. Signed-off-by: Sunil V L --- Documentation/riscv/acpi.rst | 6 ++ drivers/acpi/riscv/init.c | 1 + drivers/acpi/riscv/init.h | 1 + drivers/acpi/riscv/irqchip.c | 183 +++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+) diff --git a/Documentation/riscv/acpi.rst b/Documentation/riscv/acpi.rst index e2406546bc16..9ea9008288ea 100644 --- a/Documentation/riscv/acpi.rst +++ b/Documentation/riscv/acpi.rst @@ -29,3 +29,9 @@ properties are created using the data in MADT table. ``riscv,ext-intc-id`` - The unique ID of the external interrupts connected to this hart. + +2) RISC-V Advanced Platform Level Interrupt Controller (APLIC) +----------- + +``riscv,gsi-base`` - The global system interrupt number where this APLIC’s +interrupt inputs start. diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c index be61c08ea385..ee747211174f 100644 --- a/drivers/acpi/riscv/init.c +++ b/drivers/acpi/riscv/init.c @@ -11,4 +11,5 @@ void __init acpi_riscv_init(void) { riscv_acpi_imsic_platform_init(); + riscv_acpi_aplic_platform_init(); } diff --git a/drivers/acpi/riscv/init.h b/drivers/acpi/riscv/init.h index a2f72bb294d3..17bcf0baaadb 100644 --- a/drivers/acpi/riscv/init.h +++ b/drivers/acpi/riscv/init.h @@ -2,3 +2,4 @@ #include void __init riscv_acpi_imsic_platform_init(void); +void __init riscv_acpi_aplic_platform_init(void); diff --git a/drivers/acpi/riscv/irqchip.c b/drivers/acpi/riscv/irqchip.c index ca96bf109cf7..7fb7befdb303 100644 --- a/drivers/acpi/riscv/irqchip.c +++ b/drivers/acpi/riscv/irqchip.c @@ -23,6 +23,8 @@ LIST_HEAD(rintc_list); static struct fwnode_handle *imsic_acpi_fwnode; +LIST_HEAD(aplic_list); + struct fwnode_handle *acpi_rintc_create_irqchip_fwnode(struct acpi_madt_rintc *rintc) { struct property_entry props[6] = {}; @@ -124,3 +126,184 @@ void __init riscv_acpi_imsic_platform_init(void) if (ret) platform_device_put(pdev); } + +/* + * The ext_intc_id format is as follows: + * Bits [31:24] APLIC/PLIC ID + * Bits [15:0] APLIC IDC ID / PLIC S-Mode Context ID for this hart + */ +#define APLIC_PLIC_ID(x) ((x) >> 24) +#define IDC_CONTEXT_ID(x) ((x) & 0x0000ffff) + +static struct fwnode_handle *acpi_ext_intc_get_rintc_fwnode(u8 aplic_plic_id, u16 index) +{ + struct riscv_irqchip_list *rintc_element; + struct fwnode_handle *fwnode; + struct list_head *i, *tmp; + u32 id; + int rc; + + list_for_each_safe(i, tmp, &rintc_list) { + rintc_element = list_entry(i, struct riscv_irqchip_list, list); + fwnode = rintc_element->fwnode; + rc = fwnode_property_read_u32_array(fwnode, "riscv,ext-intc-id", &id, 1); + if (rc) + continue; + + if ((APLIC_PLIC_ID(id) == aplic_plic_id) && (IDC_CONTEXT_ID(id) == index)) + return fwnode; + } + + return NULL; +} + +static struct fwnode_handle *acpi_aplic_create_fwnode(struct acpi_madt_aplic *aplic) +{ + struct fwnode_handle *fwnode, *parent_fwnode; + struct riscv_irqchip_list *aplic_element; + struct software_node_ref_args *refs; + struct property_entry props[8] = {}; + unsigned int i; + + props[0] = PROPERTY_ENTRY_U32("riscv,gsi-base", aplic->gsi_base); + props[1] = PROPERTY_ENTRY_U32("riscv,num-sources", aplic->num_sources); + props[2] = PROPERTY_ENTRY_U32("riscv,num-idcs", aplic->num_idcs); + props[3] = PROPERTY_ENTRY_U32("riscv,aplic-id", aplic->id); + props[4] = PROPERTY_ENTRY_U64("riscv,aplic-base", aplic->base_addr); + props[5] = PROPERTY_ENTRY_U32("riscv,aplic-size", aplic->size); + if (aplic->num_idcs) { + refs = kcalloc(aplic->num_idcs, sizeof(*refs), GFP_KERNEL); + if (!refs) + return NULL; + + for (i = 0; i < aplic->num_idcs; i++) { + parent_fwnode = acpi_ext_intc_get_rintc_fwnode(aplic->id, i); + refs[i] = SOFTWARE_NODE_REFERENCE(to_software_node(parent_fwnode), + RV_IRQ_EXT); + } + props[6] = PROPERTY_ENTRY_REF_ARRAY_LEN("interrupts-extended", + refs, aplic->num_idcs); + } else { + props[6] = PROPERTY_ENTRY_BOOL("msi-parent"); + } + + fwnode = fwnode_create_software_node_early(props, NULL); + + if (fwnode) { + aplic_element = kzalloc(sizeof(*aplic_element), GFP_KERNEL); + if (!aplic_element) { + fwnode_remove_software_node(fwnode); + return NULL; + } + + aplic_element->fwnode = fwnode; + list_add_tail(&aplic_element->list, &aplic_list); + } + + return fwnode; +} + +static struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi) +{ + struct riscv_irqchip_list *aplic_element; + struct fwnode_handle *fwnode; + struct list_head *i, *tmp; + u32 gsi_base; + u32 nr_irqs; + int rc; + + list_for_each_safe(i, tmp, &aplic_list) { + aplic_element = list_entry(i, struct riscv_irqchip_list, list); + fwnode = aplic_element->fwnode; + rc = fwnode_property_read_u32_array(fwnode, "riscv,gsi-base", &gsi_base, 1); + if (!rc) { + rc = fwnode_property_read_u32_array(fwnode, "riscv,num-sources", + &nr_irqs, 1); + if (!rc && (gsi >= gsi_base && gsi < gsi_base + nr_irqs)) + return fwnode; + } + } + + return NULL; +} + +static u32 __init aplic_gsi_to_irq(u32 gsi) +{ + return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); +} + +static int __init aplic_create_platform_device(struct fwnode_handle *fwnode) +{ + struct platform_device *pdev; + u32 aplic_size, aplic_id; + struct resource *res; + u64 aplic_base; + int ret; + + if (!fwnode) + return -ENODEV; + + ret = fwnode_property_read_u64_array(fwnode, "riscv,aplic-base", &aplic_base, 1); + if (ret) + return -ENODEV; + + ret = fwnode_property_read_u32_array(fwnode, "riscv,aplic-size", &aplic_size, 1); + if (ret) + return -ENODEV; + + ret = fwnode_property_read_u32_array(fwnode, "riscv,aplic-id", &aplic_id, 1); + if (ret) + return -ENODEV; + + pdev = platform_device_alloc("riscv-aplic", aplic_id); + if (!pdev) + return -ENOMEM; + + res = kcalloc(1, sizeof(*res), GFP_KERNEL); + if (!res) { + ret = -ENOMEM; + goto dev_put; + } + + res->start = aplic_base; + res->end = res->start + aplic_size - 1; + res->flags = IORESOURCE_MEM; + ret = platform_device_add_resources(pdev, res, 1); + /* + * Resources are duplicated in platform_device_add_resources, + * free their allocated memory + */ + kfree(res); + + pdev->dev.fwnode = fwnode; + ret = platform_device_add(pdev); + if (ret) + goto dev_put; + + return 0; + +dev_put: + platform_device_put(pdev); + return ret; +} + +static int __init aplic_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_aplic *aplic = (struct acpi_madt_aplic *)header; + struct fwnode_handle *fwnode; + + fwnode = acpi_aplic_create_fwnode(aplic); + if (fwnode) + aplic_create_platform_device(fwnode); + + return 0; +} + +void __init riscv_acpi_aplic_platform_init(void) +{ + if (acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, aplic_parse_madt, 0) > 0) { + acpi_set_irq_model(ACPI_IRQ_MODEL_APLIC, aplic_get_gsi_domain_id); + acpi_set_gsi_to_irq_fallback(aplic_gsi_to_irq); + } +}