From patchwork Wed Dec 3 00:12:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Agner X-Patchwork-Id: 5425601 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 5FE92BEEA8 for ; Wed, 3 Dec 2014 00:19:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5C26020270 for ; Wed, 3 Dec 2014 00:19:46 +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 3E37B20254 for ; Wed, 3 Dec 2014 00:19:45 +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 1Xvxcy-0008E4-Nu; Wed, 03 Dec 2014 00:17:08 +0000 Received: from mail.kmu-office.ch ([178.209.48.109]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XvxZ5-00049J-OG for linux-arm-kernel@lists.infradead.org; Wed, 03 Dec 2014 00:13:12 +0000 Received: from trochilidae.toradex.int (195-226-23-137.pool.cyberlink.ch [195.226.23.137]) by mail.kmu-office.ch (Postfix) with ESMTPSA id 2EACB5E36AA; Wed, 3 Dec 2014 01:11:48 +0100 (CET) From: Stefan Agner To: shawn.guo@linaro.org, kernel@pengutronix.de, linux@arm.linux.org.uk, u.kleine-koenig@pengutronix.de, jason@lakedaemon.net, olof@lixom.net, arnd@arndb.de, daniel.lezcano@linaro.org, tglx@linutronix.de, mark.rutland@arm.com, pawel.moll@arm.com, robh+dt@kernel.org, ijc+devicetree@hellion.org.uk, galak@codeaurora.org Subject: [PATCH 06/12] ARM: imx: add support for MSCM interrupt router Date: Wed, 3 Dec 2014 01:12:05 +0100 Message-Id: <1417565531-4507-7-git-send-email-stefan@agner.ch> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1417565531-4507-1-git-send-email-stefan@agner.ch> References: <1417565531-4507-1-git-send-email-stefan@agner.ch> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141202_161308_208246_3FD67450 X-CRM114-Status: GOOD ( 19.10 ) X-Spam-Score: 0.0 (/) Cc: devicetree@vger.kernel.org, Stefan Agner , linux-kernel@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=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, 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 This adds support for Vybrids interrupt router for the shared peripherals. The router is part of the MSCM (Miscellaneous System Control Module). Signed-off-by: Stefan Agner --- arch/arm/mach-imx/Kconfig | 4 ++ arch/arm/mach-imx/Makefile | 1 + arch/arm/mach-imx/common.h | 1 + arch/arm/mach-imx/mach-vf610.c | 7 ++ arch/arm/mach-imx/mscm-vf610.c | 141 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 arch/arm/mach-imx/mscm-vf610.c diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e8627e0..2935972 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -58,6 +58,9 @@ config HAVE_IMX_SRC def_bool y if SMP select ARCH_HAS_RESET_CONTROLLER +config HAVE_VF610_MSCM + bool + config IMX_HAVE_IOMUX_V1 bool @@ -631,6 +634,7 @@ config SOC_IMX6SX config SOC_VF610 bool "Vybrid Family VF610 support" + select HAVE_VF610_MSCM select ARM_GIC select PINCTRL_VF610 select PL310_ERRATA_769419 if CACHE_L2X0 diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index f5ac685..82b1159 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_SOC_IMX50) += mach-imx50.o obj-$(CONFIG_SOC_IMX51) += mach-imx51.o obj-$(CONFIG_SOC_IMX53) += mach-imx53.o +obj-$(CONFIG_HAVE_VF610_MSCM) += mscm-vf610.o obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 59ce8f3..6b5cad9 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -103,6 +103,7 @@ static inline void imx_smp_prepare(void) {} #endif void imx_src_init(void); void imx_gpc_init(void); +void vf610_mscm_init(void); void imx_gpc_pre_suspend(bool arm_power_off); void imx_gpc_post_resume(void); void imx_gpc_mask_all(void); diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index c11ab6a..d1d200d 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -12,6 +12,12 @@ #include #include +static void __init vf610_init_irq(void) +{ + vf610_mscm_init(); + irqchip_init(); +} + static const char * const vf610_dt_compat[] __initconst = { "fsl,vf610", NULL, @@ -20,5 +26,6 @@ static const char * const vf610_dt_compat[] __initconst = { DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, + .init_irq = vf610_init_irq, .dt_compat = vf610_dt_compat, MACHINE_END diff --git a/arch/arm/mach-imx/mscm-vf610.c b/arch/arm/mach-imx/mscm-vf610.c new file mode 100644 index 0000000..211ea10 --- /dev/null +++ b/arch/arm/mach-imx/mscm-vf610.c @@ -0,0 +1,141 @@ +/* + * Copyright 2014 Stefan Agner + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +#define MSCM_CPxNUM 0x4 +#define MSCM_IRSPRC(n) (0x880 + 2 * (n)) +#define MSCM_IRSPRC_CPEN_MASK 0x3 + +#define MSCM_IRSPRC_NUM 112 + +#ifdef CONFIG_ARM_GIC +#define MSCM_IRQ_OFFSET 32 +#elif CONFIG_ARM_NVIC +#define MSCM_IRQ_OFFSET 0 +#endif + +static void __iomem *mscm_base; +static u16 mscm_saved_irsprc[MSCM_IRSPRC_NUM]; +static u16 cpu_id; + +static int vf610_mscm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + int i; + + /* Only the primary (boot CPU) should do suspend/resume */ + if (cpu_id > 0) + return NOTIFY_OK; + + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + for (i = 0; i < MSCM_IRSPRC_NUM; i++) + mscm_saved_irsprc[i] = + readw_relaxed(mscm_base + MSCM_IRSPRC(i)); + break; + case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_EXIT: + for (i = 0; i < MSCM_IRSPRC_NUM; i++) + writew_relaxed(mscm_saved_irsprc[i], + mscm_base + MSCM_IRSPRC(i)); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block mscm_notifier_block = { + .notifier_call = vf610_mscm_notifier, +}; + +static int vf610_mscm_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + u16 irsprc; + + /* Do not handle non interrupt router IRQs */ + if (hw < MSCM_IRQ_OFFSET) + return 0; + + hw -= MSCM_IRQ_OFFSET; + irsprc = readw_relaxed(mscm_base + MSCM_IRSPRC(hw)); + irsprc &= MSCM_IRSPRC_CPEN_MASK; + + WARN_ON(irsprc); + + writew_relaxed(0x1 << cpu_id, mscm_base + MSCM_IRSPRC(hw)); + + return 0; +} + +static void vf610_mscm_domain_unmap(struct irq_domain *d, unsigned int irq) +{ + irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq; + u16 irsprc; + + /* Do not handle non interrupt router IRQs */ + if (hw < MSCM_IRQ_OFFSET) + return; + + hw -= MSCM_IRQ_OFFSET; + irsprc = readw_relaxed(mscm_base + MSCM_IRSPRC(hw)); + irsprc &= MSCM_IRSPRC_CPEN_MASK; + + WARN_ON(irsprc & ~(0x1 << cpu_id)); + + writew_relaxed(0x1 << cpu_id, mscm_base + MSCM_IRSPRC(hw)); +} + +static int vf610_mscm_domain_xlate(struct irq_domain *d, + struct device_node *controller, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ +#ifdef CONFIG_ARM_GIC + *out_hwirq += 16; +#endif + return 0; +} +static const struct irq_domain_ops routable_irq_domain_ops = { + .map = vf610_mscm_domain_map, + .unmap = vf610_mscm_domain_unmap, + .xlate = vf610_mscm_domain_xlate, +}; + +void __init vf610_mscm_init(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "fsl,vf610-mscm"); + mscm_base = of_iomap(np, 0); + + if (!mscm_base) { + WARN_ON(1); + return; + } + + cpu_id = readl_relaxed(mscm_base + MSCM_CPxNUM); + + /* Register MSCM as interrupt router */ + register_routable_domain_ops(&routable_irq_domain_ops); + + cpu_pm_register_notifier(&mscm_notifier_block); +}