From patchwork Thu Feb 12 17:45:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Coquelin X-Patchwork-Id: 5821671 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 866529F37F for ; Thu, 12 Feb 2015 19:43:29 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9D1D22022A for ; Thu, 12 Feb 2015 19:43:28 +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 9608B201ED for ; Thu, 12 Feb 2015 19:43:27 +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 1YLzck-0006Xd-Q1; Thu, 12 Feb 2015 19:40:30 +0000 Received: from mail-wg0-x243.google.com ([2a00:1450:400c:c00::243]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YLzaW-0003iJ-Pz for linux-arm-kernel@lists.infradead.org; Thu, 12 Feb 2015 19:38:14 +0000 Received: by mail-wg0-f67.google.com with SMTP id b13so3724720wgh.2 for ; Thu, 12 Feb 2015 11:37:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references; bh=4emW01YCls1OdIRT2ebHJNykfYO2hdQZe43O6d0nDTk=; b=JPnhDW1a2PDDdBQ3K1G4FnvEw74gHMVpy98/kQTQgvO9nFQ0NE+F/wINektnG2DSFx oqe/K81N+2Qcbu9ewSPP3Lu67TyocPR+iqH7+Gf7noHZ6FgQ1huMv/fzYNyaudT9+7Do 0+3y/pwLfbkTRNyL7ICmmczZHM8YZlQxI+PhQgo+69VQbzgkvsA6wNkdtt0O4fuBk2m7 mBzHKcNKFM/53Syd7VAbS3Xpf5OaLHRLkYFybssrQDGkBJY7UFtwq7tUssU+2f3vq6Ak /gen5zqUUFn1uTrEsiIZfESYz2YNHsvPwMCR9Hf+WWTh0CbMkP+66HT8KOnGbT7AlCAr Os7g== X-Received: by 10.194.60.205 with SMTP id j13mr10534263wjr.42.1423763189598; Thu, 12 Feb 2015 09:46:29 -0800 (PST) Received: from lmecul0520.st.com. (157.162.113.78.rev.sfr.net. [78.113.162.157]) by mx.google.com with ESMTPSA id ka1sm6614924wjc.2.2015.02.12.09.46.26 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 12 Feb 2015 09:46:29 -0800 (PST) From: Maxime Coquelin To: Jonathan Corbet , Maxime Coquelin , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Philipp Zabel , Russell King , Daniel Lezcano , Thomas Gleixner , Linus Walleij , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Andrew Morton , "David S. Miller" , Mauro Carvalho Chehab , Joe Perches , Antti Palosaari , Tejun Heo , Will Deacon , Nikolay Borisov , Rusty Russell , Kees Cook , Michal Marek , linux-doc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH 06/14] drivers: reset: Add STM32 reset driver Date: Thu, 12 Feb 2015 18:45:56 +0100 Message-Id: <1423763164-5606-7-git-send-email-mcoquelin.stm32@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1423763164-5606-1-git-send-email-mcoquelin.stm32@gmail.com> References: <1423763164-5606-1-git-send-email-mcoquelin.stm32@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150212_113813_214960_DE5F97BD X-CRM114-Status: GOOD ( 16.97 ) X-Spam-Score: -0.6 (/) 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=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 The STM32 MCUs family IP can be reset by accessing some shared registers. The specificity is that some reset lines are used by the timers. At timer initialization time, the timer has to be reset, that's why we cannot use a regular driver. Signed-off-by: Maxime Coquelin --- .../devicetree/bindings/reset/st,stm32-reset.txt | 19 ++++ drivers/reset/Makefile | 1 + drivers/reset/reset-stm32.c | 124 +++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-reset.txt create mode 100644 drivers/reset/reset-stm32.c diff --git a/Documentation/devicetree/bindings/reset/st,stm32-reset.txt b/Documentation/devicetree/bindings/reset/st,stm32-reset.txt new file mode 100644 index 0000000..add1298 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/st,stm32-reset.txt @@ -0,0 +1,19 @@ +STMicroelectronics STM32 Peripheral Reset Controller +==================================================== + +Please also refer to reset.txt in this directory for common reset +controller binding usage. + +Required properties: +- compatible: Should be "st,stm32-reset" +- reg: should be register base and length as documented in the + datasheet +- #reset-cells: 1, see below + +example: + +reset_ahb1: reset@40023810 { + #reset-cells = <1>; + compatible = "st,stm32-reset"; + reg = <0x40023810 0x4>; +}; diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 157d421..aed12d1 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o +obj-$(CONFIG_ARCH_STM32) += reset-stm32.o obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o obj-$(CONFIG_ARCH_STI) += sti/ diff --git a/drivers/reset/reset-stm32.c b/drivers/reset/reset-stm32.c new file mode 100644 index 0000000..7a96677 --- /dev/null +++ b/drivers/reset/reset-stm32.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + * + * Heavily based on sunxi driver from Maxime Ripard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct stm32_reset_data { + spinlock_t lock; + void __iomem *membase; + struct reset_controller_dev rcdev; +}; + +static int stm32_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = container_of(rcdev, + struct stm32_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl_relaxed(data->membase + (bank * 4)); + writel_relaxed(reg | BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = container_of(rcdev, + struct stm32_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl_relaxed(data->membase + (bank * 4)); + writel_relaxed(reg & ~BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, +}; + +static void stm32_reset_init(struct device_node *np) +{ + struct stm32_reset_data *data; + struct resource res; + resource_size_t size; + int err; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + err = of_address_to_resource(np, 0, &res); + if (err) + goto err_alloc; + + size = resource_size(&res); + if (!request_mem_region(res.start, size, np->name)) { + err = -EINVAL; + goto err_alloc; + } + + data->membase = ioremap(res.start, size); + if (!data->membase) { + err = -ENOMEM; + goto err_alloc; + } + + spin_lock_init(&data->lock); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = size * 8; + data->rcdev.ops = &stm32_reset_ops; + data->rcdev.of_node = np; + + err = reset_controller_register(&data->rcdev); + if (err) + goto err_iomap; + + pr_info("%s: %d reset lines registered\n", np->full_name, + data->rcdev.nr_resets); + return; + +err_iomap: + iounmap(data->membase); +err_alloc: + kfree(data); + pr_err("%s: Reset ctrl registration failed (%d).\n", + np->full_name, err); +} + +RESET_CONTROLLER_OF_DECLARE(stm32, "st,stm32-reset", stm32_reset_init); +