From patchwork Sat Oct 5 14:39:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 2991351 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 AD7DFBF924 for ; Sat, 5 Oct 2013 14:42:11 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C4A882022A for ; Sat, 5 Oct 2013 14:42:10 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E9FBF20184 for ; Sat, 5 Oct 2013 14:42:05 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VST29-0004du-JC; Sat, 05 Oct 2013 14:40:42 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VST1o-0002D6-Ac; Sat, 05 Oct 2013 14:40:20 +0000 Received: from top.free-electrons.com ([176.31.233.9] helo=mail.free-electrons.com) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VST1H-00029Y-90 for linux-arm-kernel@lists.infradead.org; Sat, 05 Oct 2013 14:39:50 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 038088B5; Sat, 5 Oct 2013 16:39:31 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from localhost (189.58.26.109.rev.sfr.net [109.26.58.189]) by mail.free-electrons.com (Postfix) with ESMTPSA id BC0CC891; Sat, 5 Oct 2013 16:39:31 +0200 (CEST) From: Maxime Ripard To: p.zabel@pengutronix.de Subject: [PATCH 1/4] reset: Add Allwinner A31 Reset Controller Driver Date: Sat, 5 Oct 2013 16:39:17 +0200 Message-Id: <1380983960-11087-2-git-send-email-maxime.ripard@free-electrons.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1380983960-11087-1-git-send-email-maxime.ripard@free-electrons.com> References: <1380983960-11087-1-git-send-email-maxime.ripard@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131005_103947_602931_8AD31970 X-CRM114-Status: GOOD ( 15.92 ) X-Spam-Score: -1.9 (-) Cc: Emilio Lopez , linux-sunxi@googlegroups.com, kevin.z.m.zh@gmail.com, sunny@allwinnertech.com, shuge@allwinnertech.com, Maxime Ripard , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 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-Virus-Scanned: ClamAV using ClamSMTP The Allwinner A31 has an IP maintaining a few other IPs in the SoC in reset by default. Among these IPs are the High Speed Timers, hence why we can't use the regular driver construct, and need to call the registering function directly during machine initialisation. Signed-off-by: Maxime Ripard --- drivers/reset/Makefile | 1 + drivers/reset/reset-sun6i.c | 102 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 drivers/reset/reset-sun6i.c diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1e2d83f..f216b74 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o +obj-$(CONFIG_ARCH_SUNXI) += reset-sun6i.o diff --git a/drivers/reset/reset-sun6i.c b/drivers/reset/reset-sun6i.c new file mode 100644 index 0000000..e96db8d --- /dev/null +++ b/drivers/reset/reset-sun6i.c @@ -0,0 +1,102 @@ +/* + * Allwinner A31 Reset Controller driver + * + * Copyright 2013 Maxime Ripard + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sun6i_reset_data { + void __iomem *membase; + struct reset_controller_dev rcdev; +}; + +static int sun6i_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct sun6i_reset_data *data = container_of(rcdev, + struct sun6i_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + u32 reg = readl(data->membase + (bank * 4)); + + writel(reg & ~BIT(offset), data->membase + (bank * 4)); + + return 0; +} + +static int sun6i_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct sun6i_reset_data *data = container_of(rcdev, + struct sun6i_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + u32 reg = readl(data->membase + (bank * 4)); + + writel(reg | BIT(offset), data->membase + (bank * 4)); + + return 0; +} + +static struct reset_control_ops sun6i_reset_ops = { + .assert = sun6i_reset_assert, + .deassert = sun6i_reset_deassert, +}; + +int __init sun6i_reset_init(struct device_node *np) +{ + struct sun6i_reset_data *data; + struct resource res; + resource_size_t size; + int ret; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto err_alloc; + + size = resource_size(&res); + if (!request_mem_region(res.start, size, np->name)) { + ret = -EBUSY; + goto err_alloc; + } + + data->membase = ioremap(res.start, size); + if (!data->membase) { + ret = -ENOMEM; + goto err_alloc; + } + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = size * 32; + data->rcdev.ops = &sun6i_reset_ops; + data->rcdev.of_node = np; + reset_controller_register(&data->rcdev); + + return 0; + +err_alloc: + kfree(data); + return ret; +}