From patchwork Tue May 5 13:50:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 48035 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f197.google.com (mail-lb0-f197.google.com [209.85.217.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 5DC1520553 for ; Tue, 5 May 2015 13:53:40 +0000 (UTC) Received: by lbcne10 with SMTP id ne10sf50758496lbc.1 for ; Tue, 05 May 2015 06:53:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=4KofpXMgkON/tTCjoSmgV2Jzg6OypMfA7qHzl69abgs=; b=dden1P22IzIn5VTyeh2RwBoxJmaN1NFyjwHLBkLcm9iB0yGl0Nl5aRBNnQmLvpbOTQ DspGQydI8U3odwevFkp/jvvTHHAG3CdRDMCafC8DEehqqF0Ro1d5g+eDZpUS/Ie0uaGU GT7XgUKS7k2E3RqVqFpnhirvHvaIhbMbNjngb0mxMCuQ+g1XBUPeiDF5ZmYV0q+yqcsk uXTEg/WPHZD+RigpMslp3pRY+akgl9/3+LwVAIKCvmsMJfkxE4rQDvxXMGiFbxF3ajDF PdprD1rVkTRDdrils1Db6jYA/fqdiwmHZUIcHFkEvwPAzChJBGggeZptdQo+wD+dbRLp fDyw== X-Gm-Message-State: ALoCoQnage73XXr0e4K5akC9t+7xCWxVjTA03OELPX/FKqZ7vMMDApZW5dHQnlriO847egs/OYMs X-Received: by 10.112.13.200 with SMTP id j8mr22316122lbc.14.1430834019270; Tue, 05 May 2015 06:53:39 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.36.34 with SMTP id n2ls829320laj.15.gmail; Tue, 05 May 2015 06:53:39 -0700 (PDT) X-Received: by 10.152.204.40 with SMTP id kv8mr2923653lac.113.1430834019096; Tue, 05 May 2015 06:53:39 -0700 (PDT) Received: from mail-lb0-f178.google.com (mail-lb0-f178.google.com. [209.85.217.178]) by mx.google.com with ESMTPS id e9si12492623laa.104.2015.05.05.06.53.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 May 2015 06:53:39 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) client-ip=209.85.217.178; Received: by lbbzk7 with SMTP id zk7so129008647lbb.0 for ; Tue, 05 May 2015 06:53:39 -0700 (PDT) X-Received: by 10.152.236.40 with SMTP id ur8mr24199967lac.19.1430834018944; Tue, 05 May 2015 06:53:38 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.67.65 with SMTP id l1csp2262686lbt; Tue, 5 May 2015 06:53:37 -0700 (PDT) X-Received: by 10.70.38.195 with SMTP id i3mr52446444pdk.82.1430834016932; Tue, 05 May 2015 06:53:36 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ei4si24393749pbb.116.2015.05.05.06.53.36; Tue, 05 May 2015 06:53:36 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2992800AbbEENx1 (ORCPT + 29 others); Tue, 5 May 2015 09:53:27 -0400 Received: from mail-pd0-f175.google.com ([209.85.192.175]:35733 "EHLO mail-pd0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2992778AbbEENxL (ORCPT ); Tue, 5 May 2015 09:53:11 -0400 Received: by pdbqd1 with SMTP id qd1so196788758pdb.2 for ; Tue, 05 May 2015 06:53:10 -0700 (PDT) X-Received: by 10.70.44.199 with SMTP id g7mr51534893pdm.27.1430833990481; Tue, 05 May 2015 06:53:10 -0700 (PDT) Received: from localhost ([180.150.157.4]) by mx.google.com with ESMTPSA id qt4sm15967681pbc.86.2015.05.05.06.53.08 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 05 May 2015 06:53:08 -0700 (PDT) From: Hanjun Guo To: Marc Zyngier , Jason Cooper , Will Deacon , Catalin Marinas , "Rafael J. Wysocki" Cc: Jiang Liu , Lorenzo Pieralisi , Arnd Bergmann , Tomasz Nowicki , Grant Likely , Thomas Gleixner , Olof Johansson , linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, Hanjun Guo Subject: [RFC PATCH 8/9] irqchip / GICv3: Add ACPI support for GICv3+ initialization Date: Tue, 5 May 2015 21:50:56 +0800 Message-Id: <1430833857-30736-9-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1430833857-30736-1-git-send-email-hanjun.guo@linaro.org> References: <1430833857-30736-1-git-send-email-hanjun.guo@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: hanjun.guo@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , With the refator of gic_of_init(), GICv3/4 can be initialized by gic_init_bases() with gic distributor base address and gic redistributor region(s). So get the redistributor region base addresses from MADT GIC redistributor subtable, and the distributor base address from GICD subtable to init GICv3 irqchip in ACPI way. Signed-off-by: Tomasz Nowicki [hj: Rework this patch and fix multi issues] Signed-off-by: Hanjun Guo --- drivers/irqchip/irq-gic-v3.c | 146 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 87cf81b..11946a6 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -25,6 +26,7 @@ #include #include +#include #include #include @@ -819,6 +821,16 @@ out_free: return err; } +static int __init detect_distributor(void __iomem *dist_base) +{ + u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK; + + if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) + return -ENODEV; + + return 0; +} + #ifdef CONFIG_OF static int __init gic_of_init(struct device_node *node, struct device_node *parent) { @@ -826,7 +838,6 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare struct redist_region *rdist_regs; u64 redist_stride; u32 nr_redist_regions; - u32 reg; int err, i; dist_base = of_iomap(node, 0); @@ -836,11 +847,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare return -ENXIO; } - reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK; - if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) { + err = detect_distributor(dist_base); + if (err) { pr_err("%s: no distributor detected, giving up\n", node->full_name); - err = -ENODEV; goto out_unmap_dist; } @@ -888,3 +898,131 @@ out_unmap_dist: IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init); #endif + +#ifdef CONFIG_ACPI +static struct redist_region *redist_regs __initdata; +static u32 nr_redist_regions __initdata; +static phys_addr_t dist_phy_base __initdata; + +static int __init +gic_acpi_register_redist(u64 phys_base, u64 size) +{ + struct redist_region *redist_regs_new; + void __iomem *redist_base; + + redist_regs_new = krealloc(redist_regs, + sizeof(*redist_regs) * (nr_redist_regions + 1), + GFP_KERNEL); + if (!redist_regs_new) { + pr_err("Couldn't allocate resource for GICR region\n"); + return -ENOMEM; + } + + redist_regs = redist_regs_new; + + redist_base = ioremap(phys_base, size); + if (!redist_base) { + pr_err("Couldn't map GICR region @%llx\n", phys_base); + return -ENOMEM; + } + + redist_regs[nr_redist_regions].phys_base = phys_base; + redist_regs[nr_redist_regions].redist_base = redist_base; + nr_redist_regions++; + return 0; +} + +static int __init +gic_acpi_parse_madt_redist(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_redistributor *redist; + + if (BAD_MADT_ENTRY(header, end)) + return -EINVAL; + + redist = (struct acpi_madt_generic_redistributor *)header; + if (!redist->base_address) + return -EINVAL; + + return gic_acpi_register_redist(redist->base_address, redist->length); +} + +static int __init +gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_distributor *dist; + + dist = (struct acpi_madt_generic_distributor *)header; + + if (BAD_MADT_ENTRY(dist, end)) + return -EINVAL; + + dist_phy_base = dist->base_address; + return 0; +} + +static int __init +gic_v3_acpi_init(struct acpi_table_header *table) +{ + int count, i, err = 0; + void __iomem *dist_base; + + if (acpi_gic_version() < ACPI_MADT_GIC_VER_V3) + return -ENODEV; + + /* Get distributor base address */ + count = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + gic_acpi_parse_madt_distributor, table, + ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0); + if (count <= 0) { + pr_err("No valid GICD entry exist\n"); + return -EINVAL; + } else if (count > 1) { + pr_err("More than one GICD entry detected\n"); + return -EINVAL; + } + + dist_base = ioremap(dist_phy_base, ACPI_GICV3_DIST_MEM_SIZE); + if (!dist_base) { + pr_err("Unable to map GICD registers\n"); + return -ENOMEM; + } + + err = detect_distributor(dist_base); + if (err) { + pr_err("No distributor detected at @%p, giving up", dist_base); + goto out_dist_unmap; + } + + /* Collect redistributor base addresses */ + count = acpi_parse_entries(ACPI_SIG_MADT, + sizeof(struct acpi_table_madt), + gic_acpi_parse_madt_redist, table, + ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, 0); + if (count <= 0) { + pr_info("No valid GICR entries exist\n"); + err = -EINVAL; + goto out_redist_unmap; + } + + err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0, NULL); + if (err) + goto out_redist_unmap; + + irq_set_default_host(gic_data.domain); + return 0; + +out_redist_unmap: + for (i = 0; i < nr_redist_regions; i++) + if (redist_regs[i].redist_base) + iounmap(redist_regs[i].redist_base); + kfree(redist_regs); +out_dist_unmap: + iounmap(dist_base); + return err; +} +IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_SIG_MADT, gic_v3_acpi_init); +#endif