From patchwork Thu Dec 17 11:52:06 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 7872561 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 767B79F32E for ; Thu, 17 Dec 2015 11:55:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EA85420263 for ; Thu, 17 Dec 2015 11:55:37 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 96C2220421 for ; Thu, 17 Dec 2015 11:55:32 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a9X88-00021x-9Q; Thu, 17 Dec 2015 11:53:56 +0000 Received: from mail-wm0-x236.google.com ([2a00:1450:400c:c09::236]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a9X76-000199-Js for linux-arm-kernel@lists.infradead.org; Thu, 17 Dec 2015 11:52:57 +0000 Received: by mail-wm0-x236.google.com with SMTP id p187so19676502wmp.0 for ; Thu, 17 Dec 2015 03:52:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/HdTaBOUsvP/hPlmZmxhe0RGdHttZ+D18ATvM7GXMvM=; b=ov6N7gvFinnD2HwoBevYvNRJcKLtHhEeqUlxsxyOimGjQVF+MpM+HyHlPwzOzmuOBD QoCyDOhq/zxtU9abtFUKivhzoLYwCZzfufRKuhI7K8N3d3LgWxT7UmX4Bi30rMk7rmOj 6ZjjVLtsySClK+CZkYUcWdV/VG3/z+czyIkc9gxIp487mx+99zT2CdG92hd39JcxPv7T vKzv0x3neKLmji/sZo3wqKah14EAUbEQpUvL6RrUmBgMQ/+rQeyMRIksqSJcefQpBadM E8GtNOuzqgzy4QjLgt54e6h92K7ilArS2eA8k16UxQW37vBNtcPD+9t1GuwlbypRs4Fr KnLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/HdTaBOUsvP/hPlmZmxhe0RGdHttZ+D18ATvM7GXMvM=; b=HOVdecwiaKv0c75HSlyYhjyvpq+YTJUNZLQDm0xUE4h8fMSMwMK/saQ9vUHZvDTMwr hdDhvrJHJnatw3cUEi2os49iqkegwgdbdXTLTb3OKTwkqHT4x3QqjSp7U5v4dui3Svvt i5FnOP9+gaK58iiC45fCgMUT4aghIaUFikWQbE/kqOEoVHq02GBt7+klN0bQFCj/7iH+ OzxxArwixlPp8MSL+1JZmuwadEvBFg4Bht2Bu+z0aFI2umQ815AfMZ25hXP1Y5mv/hOp 4YemMnKHiBOhm5SWtb5PQKetpOgY0FbPp1EJfTd1jmD0gev0au31rJiLp8IwBDWLZBwy Oy8w== X-Gm-Message-State: ALoCoQlknFZe/8H/shi70939gALH2kjw2PyteO64ORF1eKhZ65DmxghQgZlie7//BrfLuqnYfFs7Mu2e5sZ3MbGVEMjTMhjEPQ== X-Received: by 10.194.5.74 with SMTP id q10mr56008545wjq.138.1450353150979; Thu, 17 Dec 2015 03:52:30 -0800 (PST) Received: from tn-HP-4.semihalf.local (cardhu.semihalf.com. [213.17.239.108]) by smtp.gmail.com with ESMTPSA id kb5sm10137208wjc.20.2015.12.17.03.52.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 17 Dec 2015 03:52:30 -0800 (PST) From: Tomasz Nowicki To: marc.zyngier@arm.com, tglx@linutronix.de, jason@lakedaemon.net, rjw@rjwysocki.net, lorenzo.pieralisi@arm.com, robert.richter@caviumnetworks.com, shijie.huang@arm.com, guohanjun@huawei.com, Suravee.Suthikulpanit@amd.com Subject: [PATCH V2 03/10] irqchip, GICv3, ACPI: Add redistributor support via GICC structures. Date: Thu, 17 Dec 2015 12:52:06 +0100 Message-Id: <1450353133-15992-4-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1450353133-15992-1-git-send-email-tn@semihalf.com> References: <1450353133-15992-1-git-send-email-tn@semihalf.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151217_035253_033630_46AEF847 X-CRM114-Status: GOOD ( 20.33 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: graeme.gregory@linaro.org, Catalin.Marinas@arm.com, will.deacon@arm.com, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, hanjun.guo@linaro.org, ddaney.cavm@gmail.com, Tomasz Nowicki , mw@semihalf.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On systems supporting GICv3 and above, in MADT GICC structures, the field of GICR Base Address holds the 64-bit physical address of the associated Redistributor if the GIC Redistributors are not in the always-on power domain, so instead of init GICR regions via GIC redistributor structure(s), init it with GICR base address in GICC structures in that case. Signed-off-by: Hanjun Guo Signed-off-by: Tomasz Nowicki --- drivers/irqchip/irq-gic-v3.c | 98 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 9 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index c4b929c..0528e82 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -39,6 +39,7 @@ struct redist_region { void __iomem *redist_base; phys_addr_t phys_base; + bool single_redist; }; struct gic_chip_data { @@ -435,6 +436,9 @@ static int gic_populate_rdist(void) return 0; } + if (gic_data.redist_regions[i].single_redist) + break; + if (gic_data.redist_stride) { ptr += gic_data.redist_stride; } else { @@ -965,6 +969,7 @@ IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init); #ifdef CONFIG_ACPI static struct redist_region *redist_regs __initdata; static u32 nr_redist_regions __initdata; +static bool single_redist; static int __init gic_acpi_register_redist(phys_addr_t phys_base, u64 size) @@ -979,7 +984,8 @@ gic_acpi_register_redist(phys_addr_t phys_base, u64 size) } redist_regs[count].phys_base = phys_base; - redist_regs[count++].redist_base = redist_base; + redist_regs[count].redist_base = redist_base; + redist_regs[count++].single_redist = single_redist; return 0; } @@ -993,6 +999,48 @@ gic_acpi_parse_madt_redist(struct acpi_subtable_header *header, return gic_acpi_register_redist(redist->base_address, redist->length); } +static int __init +gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc; + void __iomem *redist_base; + u64 typer; + u32 size; + + gicc = (struct acpi_madt_generic_interrupt *)header; + redist_base = ioremap(gicc->gicr_base_address, SZ_64K * 2); + if (!redist_base) + return -ENOMEM; + + typer = readq_relaxed(redist_base + GICR_TYPER); + /* don't map reserved page as it's buggy to access it */ + size = (typer & GICR_TYPER_VLPIS) ? SZ_64K * 3 : SZ_64K * 2; + iounmap(redist_base); + return gic_acpi_register_redist(gicc->gicr_base_address, size); +} + +static int __init gic_acpi_collect_gicr_base(void) +{ + acpi_tbl_entry_handler redist_parser; + enum acpi_madt_type type; + + if (single_redist) { + type = ACPI_MADT_TYPE_GENERIC_INTERRUPT; + redist_parser = gic_acpi_parse_madt_gicc; + } else { + type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR; + redist_parser = gic_acpi_parse_madt_redist; + } + + /* Collect redistributor base addresses in GICR entries */ + if (acpi_table_parse_madt(type, redist_parser, 0) > 0) + return 0; + + pr_info("No valid GICR entries exist\n"); + return -ENODEV; +} + static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header, const unsigned long end) { @@ -1000,6 +1048,42 @@ static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header, return 0; } +static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *gicc = + (struct acpi_madt_generic_interrupt *)header; + + /* + * If GICC is enabled and has valid gicr base address, then it means + * GICR base is presented via GICC + */ + if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) + return 0; + + return -ENODEV; +} + +static int __init gic_acpi_count_gicr_regions(void) +{ + int count; + + /* Count how many redistributor regions we have */ + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, + gic_acpi_match_gicr, 0); + if (count > 0) { + single_redist = false; + return count; + } + + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, + gic_acpi_match_gicc, 0); + if (count > 0) + single_redist = true; + + return count; +} + static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header, struct acpi_probe_entry *ape) { @@ -1011,8 +1095,7 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header, return false; /* We need to do that exercise anyway, the sooner the better */ - count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, - gic_acpi_match_gicr, 0); + count = gic_acpi_count_gicr_regions(); if (count <= 0) return false; @@ -1028,7 +1111,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end) struct acpi_madt_generic_distributor *dist; struct fwnode_handle *domain_handle; void __iomem *dist_base; - int i, err, count; + int i, err; /* Get distributor base address */ dist = (struct acpi_madt_generic_distributor *)header; @@ -1051,12 +1134,9 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end) goto out_dist_unmap; } - count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, - gic_acpi_parse_madt_redist, 0); - if (count <= 0) { - err = -ENODEV; + err = gic_acpi_collect_gicr_base(); + if (err) goto out_redist_unmap; - } domain_handle = irq_domain_alloc_fwnode(dist_base); if (!domain_handle) {