From patchwork Wed Jul 19 18:45:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeniy Paltsev X-Patchwork-Id: 791196 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-snps-arc-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iKEJEodd"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xCQvp06PZz9sxR for ; Thu, 20 Jul 2017 04:45:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=fIG3awMwxTn2gAlQ46BQjx6+0DRUkkKscSxqK30LAiA=; b=iKE JEodd7bghSUhE4Gar1W9Df2rxmmFqbad51uvxAZD0DHrCoT4R8aOiTOo5o0C9RmxGiZnK0YpiwLkw geLdLBOsK3vd+SwEutjvwxBoNZrrtBc0la3GvPdmRHMQaV0U1pS/MMkWmmAsirEhRsxHdJhnQx5SA Rgi+56Bdx/PMB3el1AaRAzZpvO/jqSECWdeaep7NriMeEoDpSNkavl6P7erjDsii12dlEbvtdgQ7H dHkYdiqDumhkt9LzZ0IAS8xYT3qy+pHokFIYX1cCuuaT7fD0U6MPh65CKi5LK9qjw/eLgGKcEEGnE L4fZa156/zuXDlgaOhH26ABy5v4joww==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dXtye-0001x1-Mv; Wed, 19 Jul 2017 18:45:40 +0000 Received: from smtprelay.synopsys.com ([198.182.60.111]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dXtya-0001vV-RO for linux-snps-arc@lists.infradead.org; Wed, 19 Jul 2017 18:45:38 +0000 Received: from mailhost.synopsys.com (mailhost2.synopsys.com [10.13.184.66]) by smtprelay.synopsys.com (Postfix) with ESMTP id 92C2A10C13C9; Wed, 19 Jul 2017 11:45:15 -0700 (PDT) Received: from mailhost.synopsys.com (localhost [127.0.0.1]) by mailhost.synopsys.com (Postfix) with ESMTP id 713573D9; Wed, 19 Jul 2017 11:45:15 -0700 (PDT) Received: from localhost.internal.synopsys.com (unknown [10.121.8.106]) by mailhost.synopsys.com (Postfix) with ESMTP id B7C5F3AC; Wed, 19 Jul 2017 11:45:13 -0700 (PDT) From: Eugeniy Paltsev To: Philipp Zabel Subject: [PATCH v2] ARC: reset: introduce HSDKv1 reset driver Date: Wed, 19 Jul 2017 21:45:11 +0300 Message-Id: <20170719184511.18497-1-Eugeniy.Paltsev@synopsys.com> X-Mailer: git-send-email 2.9.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170719_114536_960130_406AE18F X-CRM114-Status: GOOD ( 16.18 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [198.182.60.111 listed in list.dnswl.org] -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-snps-arc@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux on Synopsys ARC Processors List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Rob Herring , linux-snps-arc@lists.infradead.org, Eugeniy Paltsev MIME-Version: 1.0 Sender: "linux-snps-arc" Errors-To: linux-snps-arc-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The HSDK v1 periphery IPs can be reset by accessing some registers from the CGU block. The list of available reset lines is documented in the DT bindings. Signed-off-by: Eugeniy Paltsev --- Changes v1 -> v2: - Remove defines of the unused registers. - Map io memory only for single CGU_SYS_RST_CTRL register instead of CGU_SYS_*_CTRL, as we use only CGU_SYS_RST_CTRL. .../bindings/reset/snps,hsdk-v1-reset.txt | 28 +++++ MAINTAINERS | 7 ++ drivers/reset/Kconfig | 6 + drivers/reset/Makefile | 1 + drivers/reset/reset-hsdk-v1.c | 137 +++++++++++++++++++++ include/dt-bindings/reset/snps,hsdk-v1-reset.h | 17 +++ 6 files changed, 196 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt create mode 100644 drivers/reset/reset-hsdk-v1.c create mode 100644 include/dt-bindings/reset/snps,hsdk-v1-reset.h diff --git a/Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt b/Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt new file mode 100644 index 0000000..6a68146 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt @@ -0,0 +1,28 @@ +Binding for the HSDK v1 reset controller + +This binding uses the common reset binding[1]. + +[1] Documentation/devicetree/bindings/reset/reset.txt + +Required properties: +- compatible: should be "snps,hsdk-v1.0-reset". +- reg: should always contain 2 pairs address - length: first for reset + configuration register and second for corresponding SW reset and status bits + register. +- #reset-cells: from common reset binding; Should always be set to 1. + +Example: + reset: reset@880 { + compatible = "snps,hsdk-v1.0-reset"; + #reset-cells = <1>; + reg = <0x8A0 0x4>, <0xFF0 0x4>; + }; + +Specifying reset lines connected to IP modules: + ethernet@.... { + .... + resets = <&reset HSDK_V1_ETH_RESET>; + .... + }; + +The index could be found in diff --git a/MAINTAINERS b/MAINTAINERS index 09b5ab6..99deabb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11307,6 +11307,13 @@ L: linux-mmc@vger.kernel.org S: Maintained F: drivers/mmc/host/dw_mmc* +SYNOPSYS HSDK RESET CONTROLLER DRIVER +M: Eugeniy Paltsev +S: Supported +F: drivers/reset/reset-hsdk-v1.c +F: include/dt-bindings/reset/snps,hsdk-v1-reset.h +F: Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt + SYSTEM TRACE MODULE CLASS M: Alexander Shishkin S: Maintained diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index d21c07c..cb13f0d 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,6 +34,12 @@ config RESET_BERLIN help This enables the reset controller driver for Marvell Berlin SoCs. +config RESET_HSDK_V1 + bool "HSDK v1 Reset Driver" + default n + help + This enables the reset controller driver for HSDK v1. + config RESET_IMX7 bool "i.MX7 Reset Driver" if COMPILE_TEST default SOC_IMX7D diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 02a74db..772e5f2 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o obj-$(CONFIG_RESET_ATH79) += reset-ath79.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o +obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_MESON) += reset-meson.o diff --git a/drivers/reset/reset-hsdk-v1.c b/drivers/reset/reset-hsdk-v1.c new file mode 100644 index 0000000..bca13e4 --- /dev/null +++ b/drivers/reset/reset-hsdk-v1.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 Synopsys. + * + * Synopsys HSDKv1 SDP reset driver. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev) + +struct hsdkv1_rst { + void __iomem *regs_ctl; + void __iomem *regs_rst; + spinlock_t lock; + struct reset_controller_dev rcdev; +}; + +static const u32 rst_map[] = { + BIT(16), /* APB_RST */ + BIT(17), /* AXI_RST */ + BIT(18), /* ETH_RST */ + BIT(19), /* USB_RST */ + BIT(20), /* SDIO_RST */ + BIT(21), /* HDMI_RST */ + BIT(22), /* GFX_RST */ + BIT(25), /* DMAC_RST */ + BIT(31), /* EBI_RST */ +}; + +#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map) + +#define CGU_SYS_RST_CTRL 0x0 +#define CGU_IP_SW_RESET 0x0 +#define CGU_IP_SW_RESET_DELAY_SHIFT 16 +#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT) +#define CGU_IP_SW_RESET_DELAY 0 +#define CGU_IP_SW_RESET_RESET BIT(0) +#define SW_RESET_TIMEOUT 10000 + +static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id) +{ + writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL); +} + +static int hsdkv1_reset_do(struct hsdkv1_rst *rst) +{ + u32 reg; + + reg = readl(rst->regs_rst + CGU_IP_SW_RESET); + reg &= ~CGU_IP_SW_RESET_DELAY_MASK; + reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT; + reg |= CGU_IP_SW_RESET_RESET; + writel(reg, rst->regs_rst + CGU_IP_SW_RESET); + + /* wait till reset bit is back to 0 */ + return readl_poll_timeout_atomic(rst->regs_rst + CGU_IP_SW_RESET, reg, + !(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT); +} + +static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&rst->lock, flags); + hsdkv1_reset_config(rst, id); + ret = hsdkv1_reset_do(rst); + spin_unlock_irqrestore(&rst->lock, flags); + + return ret; +} + +static const struct reset_control_ops hsdkv1_reset_ops = { + .reset = hsdkv1_reset_reset, +}; + +static int hsdkv1_reset_probe(struct platform_device *pdev) +{ + struct hsdkv1_rst *rst; + struct resource *mem; + + rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); + if (!rst) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_ctl)) + return PTR_ERR(rst->regs_ctl); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_rst)) + return PTR_ERR(rst->regs_rst); + + spin_lock_init(&rst->lock); + + rst->rcdev.owner = THIS_MODULE; + rst->rcdev.ops = &hsdkv1_reset_ops; + rst->rcdev.of_node = pdev->dev.of_node; + rst->rcdev.nr_resets = HSDK_MAX_RESETS; + rst->rcdev.of_reset_n_cells = 1; + + return reset_controller_register(&rst->rcdev); +} + +static const struct of_device_id hsdkv1_reset_dt_match[] = { + { .compatible = "snps,hsdk-v1.0-reset" }, + { }, +}; + +static struct platform_driver hsdkv1_reset_driver = { + .probe = hsdkv1_reset_probe, + .driver = { + .name = "hsdk-v1.0-reset", + .of_match_table = hsdkv1_reset_dt_match, + }, +}; +builtin_platform_driver(hsdkv1_reset_driver); + +MODULE_AUTHOR("Eugeniy Paltsev "); +MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/reset/snps,hsdk-v1-reset.h b/include/dt-bindings/reset/snps,hsdk-v1-reset.h new file mode 100644 index 0000000..d898c89 --- /dev/null +++ b/include/dt-bindings/reset/snps,hsdk-v1-reset.h @@ -0,0 +1,17 @@ +/** + * This header provides index for the HSDK v1 reset controller. + */ +#ifndef _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1 +#define _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1 + +#define HSDK_V1_APB_RESET 0 +#define HSDK_V1_AXI_RESET 1 +#define HSDK_V1_ETH_RESET 2 +#define HSDK_V1_USB_RESET 3 +#define HSDK_V1_SDIO_RESET 4 +#define HSDK_V1_HDMI_RESET 5 +#define HSDK_V1_GFX_RESET 6 +#define HSDK_V1_DMAC_RESET 7 +#define HSDK_V1_EBI_RESET 8 + +#endif /*_DT_BINDINGS_RESET_CONTROLLER_HSDK_V1*/