From patchwork Thu Aug 28 15:31:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 4805541 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6509EC0338 for ; Thu, 28 Aug 2014 15:35:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 40B54200EC for ; Thu, 28 Aug 2014 15:35:32 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2FF1520142 for ; Thu, 28 Aug 2014 15:35:30 +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 1XN1gG-00029i-I0; Thu, 28 Aug 2014 15:32:08 +0000 Received: from mail-we0-x235.google.com ([2a00:1450:400c:c03::235]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XN1fz-00020y-Nm for linux-arm-kernel@lists.infradead.org; Thu, 28 Aug 2014 15:31:52 +0000 Received: by mail-we0-f181.google.com with SMTP id x48so947440wes.40 for ; Thu, 28 Aug 2014 08:31:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wM2gQDOUsPyePFOk/kmdzYkgqxmK2paDIecMPEMzxq0=; b=ez8rDnFShhui9ih4c2WqNXt7FrN2Y4xiTn/dkCjtB9/fAhz7TdFp7rFXFcmkcNIgYE 2fFnoeC+ZK9CA9afOc/4lpcSJtH2lgQgzL3zKkwq3UwSl/agFA+r6jBOi6etAMxR22jP ON50W/n0WCvw42JAH4zdAt7Xf+5n1NOry8lvwey4j2e0Uxk6XgkWtYPd7pwKsx2XV8Ee AS6Eegsl5sNdvxJD7GRexHo6gfUIrUwEJTuJVjXaMCFTvALRaS98vqAgaEywarp3p4T5 0uSDbfKsCqViV45RMZBKDM9A46iFEwj08DX6KxEaNob6r9PckW7gDbFsAaiYX3USlU6T VuhQ== X-Received: by 10.194.122.6 with SMTP id lo6mr6201820wjb.17.1409239889642; Thu, 28 Aug 2014 08:31:29 -0700 (PDT) Received: from localhost (port-14388.pppoe.wtnet.de. [84.46.56.108]) by mx.google.com with ESMTPSA id ga9sm10716046wjb.45.2014.08.28.08.31.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Aug 2014 08:31:28 -0700 (PDT) From: Thierry Reding To: Stephen Warren Subject: [PATCH v4 3/5] ARM: tegra: Initialize interrupt controller from DT Date: Thu, 28 Aug 2014 17:31:17 +0200 Message-Id: <1409239879-12376-3-git-send-email-thierry.reding@gmail.com> X-Mailer: git-send-email 2.0.4 In-Reply-To: <1409239879-12376-1-git-send-email-thierry.reding@gmail.com> References: <1409239879-12376-1-git-send-email-thierry.reding@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140828_083152_073663_93EBB6AA X-CRM114-Status: GOOD ( 21.78 ) X-Spam-Score: -0.8 (/) Cc: linux-tegra@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no 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 From: Thierry Reding Obtains the register ranges for the legacy interrupt controller from DT and provide hard-coded values as fallback. Signed-off-by: Thierry Reding --- Changes in v4: - check for Tegra20 in non-DT fallback using of_machine_is_compatible() - cleanup warning messages Changes in v3: - fixup subject prefix Changes in v2: - check for the exact number of controllers expected - fallback to tegra_chip_id for non-DT - warn on parsing errors arch/arm/mach-tegra/iomap.h | 18 ------- arch/arm/mach-tegra/irq.c | 122 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 101 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h index ee79808e93a3..52bbb5c8fe84 100644 --- a/arch/arm/mach-tegra/iomap.h +++ b/arch/arm/mach-tegra/iomap.h @@ -28,24 +28,6 @@ #define TEGRA_ARM_PERIF_BASE 0x50040000 #define TEGRA_ARM_PERIF_SIZE SZ_8K -#define TEGRA_ARM_INT_DIST_BASE 0x50041000 -#define TEGRA_ARM_INT_DIST_SIZE SZ_4K - -#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 -#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 - -#define TEGRA_SECONDARY_ICTLR_BASE 0x60004100 -#define TEGRA_SECONDARY_ICTLR_SIZE SZ_64 - -#define TEGRA_TERTIARY_ICTLR_BASE 0x60004200 -#define TEGRA_TERTIARY_ICTLR_SIZE SZ_64 - -#define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300 -#define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64 - -#define TEGRA_QUINARY_ICTLR_BASE 0x60004400 -#define TEGRA_QUINARY_ICTLR_SIZE SZ_64 - #define TEGRA_TMR1_BASE 0x60005000 #define TEGRA_TMR1_SIZE SZ_8 diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index da7be13aecce..636ebfd466cb 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -27,8 +27,7 @@ #include #include -#include "board.h" -#include "iomap.h" +#include #define ICTLR_CPU_IEP_VFIQ 0x08 #define ICTLR_CPU_IEP_FIR 0x14 @@ -52,13 +51,7 @@ static int num_ictlrs; -static void __iomem *ictlr_reg_base[] = { - IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), - IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), - IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE), - IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), - IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE), -}; +static void __iomem *ictlr_reg_base[] = { NULL, NULL, NULL, NULL, NULL }; #ifdef CONFIG_PM_SLEEP static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS]; @@ -70,10 +63,11 @@ static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS]; static void __iomem *tegra_gic_cpu_base; #endif +static void __iomem *distbase; + bool tegra_pending_sgi(void) { u32 pending_set; - void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE); pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET); @@ -255,24 +249,109 @@ static void tegra114_gic_cpu_pm_registration(void) static void tegra114_gic_cpu_pm_registration(void) { } #endif +static struct resource ictlr_regs[] = { + { .start = 0x60004000, .end = 0x6000403f, .flags = IORESOURCE_MEM }, + { .start = 0x60004100, .end = 0x6000413f, .flags = IORESOURCE_MEM }, + { .start = 0x60004200, .end = 0x6000423f, .flags = IORESOURCE_MEM }, + { .start = 0x60004300, .end = 0x6000433f, .flags = IORESOURCE_MEM }, + { .start = 0x60004400, .end = 0x6000443f, .flags = IORESOURCE_MEM }, +}; + +struct tegra_ictlr_soc { + unsigned int num_ictlrs; +}; + +static const struct tegra_ictlr_soc tegra20_ictlr_soc = { + .num_ictlrs = 4, +}; + +static const struct tegra_ictlr_soc tegra30_ictlr_soc = { + .num_ictlrs = 5, +}; + +static const struct of_device_id ictlr_matches[] = { + { .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc }, + { .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc }, + { } +}; + +static const struct of_device_id gic_matches[] = { + { .compatible = "arm,cortex-a15-gic", }, + { .compatible = "arm,cortex-a9-gic", }, + { } +}; + void __init tegra_init_irq(void) { - int i; - void __iomem *distbase; + unsigned int max_ictlrs = ARRAY_SIZE(ictlr_regs), i; + const struct of_device_id *match; + struct device_node *np; + struct resource res; + + np = of_find_matching_node_and_match(NULL, ictlr_matches, &match); + if (np) { + const struct tegra_ictlr_soc *soc = match->data; + + for (i = 0; i < soc->num_ictlrs; i++) { + if (of_address_to_resource(np, i, &res) < 0) + break; + + ictlr_regs[i] = res; + } + + WARN(i != soc->num_ictlrs, + "Found %u interrupt controllers in DT; expected %u.\n", + i, soc->num_ictlrs); + + max_ictlrs = soc->num_ictlrs; + of_node_put(np); + } else { + /* + * If no matching device node was found, fall back to using + * the chip ID. + */ + + /* Tegra30 and later have five interrupt controllers, ... */ + max_ictlrs = ARRAY_SIZE(ictlr_regs); + + /* ..., but Tegra20 only has four. */ + if (of_machine_is_compatible("nvidia,tegra20")) + max_ictlrs--; + } - distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE); + memset(&res, 0, sizeof(res)); + + np = of_find_matching_node(NULL, gic_matches); + if (np) { + if (of_address_to_resource(np, 0, &res) < 0) + WARN(1, "GIC registers are missing from DT\n"); + + of_node_put(np); + } + + if (res.start == 0 || res.end == 0) { + res.start = 0x50041000; + res.end = 0x50041fff; + res.flags = IORESOURCE_MEM; + } + + distbase = ioremap_nocache(res.start, resource_size(&res)); num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f; - if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) { - WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.", - num_ictlrs, ARRAY_SIZE(ictlr_reg_base)); - num_ictlrs = ARRAY_SIZE(ictlr_reg_base); + if (num_ictlrs != max_ictlrs) { + WARN(1, "Found %u interrupt controllers; expected %u.\n", + num_ictlrs, max_ictlrs); + num_ictlrs = max_ictlrs; } for (i = 0; i < num_ictlrs; i++) { - void __iomem *ictlr = ictlr_reg_base[i]; + struct resource *regs = &ictlr_regs[i]; + void __iomem *ictlr; + + ictlr = ioremap_nocache(regs->start, resource_size(regs)); writel(~0, ictlr + ICTLR_CPU_IER_CLR); writel(0, ictlr + ICTLR_CPU_IEP_CLASS); + ictlr_reg_base[i] = ictlr; } gic_arch_extn.irq_ack = tegra_ack; @@ -287,9 +366,10 @@ void __init tegra_init_irq(void) * Check if there is a devicetree present, since the GIC will be * initialized elsewhere under DT. */ - if (!of_have_populated_dt()) - gic_init(0, 29, distbase, - IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); + if (!of_have_populated_dt()) { + void __iomem *cpubase = ioremap_nocache(0x50040000, 0x2000); + gic_init(0, 29, distbase, cpubase); + } tegra114_gic_cpu_pm_registration(); }