From patchwork Mon Sep 3 16:25:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pawel Moll X-Patchwork-Id: 1400481 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id A8032DF280 for ; Mon, 3 Sep 2012 16:29:46 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T8ZTY-0000DL-E7; Mon, 03 Sep 2012 16:26:12 +0000 Received: from service87.mimecast.com ([91.220.42.44]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T8ZT5-00006F-I3 for linux-arm-kernel@lists.infradead.org; Mon, 03 Sep 2012 16:25:48 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Mon, 03 Sep 2012 17:25:39 +0100 Received: from hornet.cambridge.arm.com ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Mon, 3 Sep 2012 17:27:44 +0100 From: Pawel Moll To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 03/11] misc: Versatile Express reset driver Date: Mon, 3 Sep 2012 17:25:23 +0100 Message-Id: <1346689531-7212-4-git-send-email-pawel.moll@arm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1346689531-7212-1-git-send-email-pawel.moll@arm.com> References: <1346689531-7212-1-git-send-email-pawel.moll@arm.com> X-OriginalArrivalTime: 03 Sep 2012 16:27:44.0795 (UTC) FILETIME=[0C2C0EB0:01CD89F1] X-MC-Unique: 112090317253905901 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [91.220.42.44 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: arm@kernel.org, Pawel Moll X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This is a simple vexpress config driver providing platform restart and power off functions. By writing to the "active" attribute of the reboot or reset device, user can decide what if the platform is supposed to execute full power cycle (reboot, default) or simply assert system level reset signal. Signed-off-by: Pawel Moll --- drivers/misc/vexpress/Makefile | 1 + drivers/misc/vexpress/reset.c | 110 ++++++++++++++++++++++++++++++++++++++++ include/linux/vexpress.h | 4 ++ 3 files changed, 115 insertions(+) create mode 100644 drivers/misc/vexpress/reset.c diff --git a/drivers/misc/vexpress/Makefile b/drivers/misc/vexpress/Makefile index 5b1e8fc..af11749 100644 --- a/drivers/misc/vexpress/Makefile +++ b/drivers/misc/vexpress/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_VEXPRESS_CONFIG_BUS) += config_bus.o +obj-$(CONFIG_VEXPRESS_CONFIG_BUS) += reset.o diff --git a/drivers/misc/vexpress/reset.c b/drivers/misc/vexpress/reset.c new file mode 100644 index 0000000..1be7cba --- /dev/null +++ b/drivers/misc/vexpress/reset.c @@ -0,0 +1,110 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Copyright (C) 2012 ARM Limited + */ + +#include +#include +#include + +static void vexpress_reset_do(struct vexpress_config_device *vecdev, + const char *what) +{ + int err = -ENOENT; + + if (vecdev) { + unsigned long timeout; + + err = vexpress_config_write(vecdev, 0, 0); + + timeout = jiffies + HZ; + while (time_before(jiffies, timeout)) + cpu_relax(); + } + + dev_emerg(&vecdev->dev, "Unable to %s (%d)\n", what, err); +} + +static struct vexpress_config_device *vexpress_power_off_device; + +void vexpress_power_off(void) +{ + vexpress_reset_do(vexpress_power_off_device, "power off"); +} + +static struct vexpress_config_device *vexpress_restart_device; + +void vexpress_restart(char str, const char *cmd) +{ + vexpress_reset_do(vexpress_restart_device, "restart"); +} + +static ssize_t vexpress_reset_active_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", vexpress_restart_device == + to_vexpress_config_device(dev)); +} + +static ssize_t vexpress_reset_active_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + long value; + int err = kstrtol(buf, 0, &value); + + if (!err && value) + vexpress_restart_device = to_vexpress_config_device(dev); + + return err ? err : count; +} + +DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show, + vexpress_reset_active_store); + + +static int vexpress_reset_probe(struct vexpress_config_device *vecdev) +{ + switch (vecdev->func) { + case VEXPRESS_CONFIG_FUNC_SHUTDOWN: + vexpress_power_off_device = vecdev; + break; + case VEXPRESS_CONFIG_FUNC_RESET: + if (!vexpress_restart_device) + vexpress_restart_device = vecdev; + device_create_file(&vecdev->dev, &dev_attr_active); + break; + case VEXPRESS_CONFIG_FUNC_REBOOT: + vexpress_restart_device = vecdev; + device_create_file(&vecdev->dev, &dev_attr_active); + break; + }; + + return 0; +} + +static const unsigned vexpress_reset_funcs[] = { + VEXPRESS_CONFIG_FUNC_RESET, + VEXPRESS_CONFIG_FUNC_SHUTDOWN, + VEXPRESS_CONFIG_FUNC_REBOOT, + 0, +}; + +static struct vexpress_config_driver vexpress_reset_driver = { + .funcs = vexpress_reset_funcs, + .probe = vexpress_reset_probe, + .driver.name = "vexpress-reset", +}; + +static int __init vexpress_reset_init(void) +{ + return vexpress_config_driver_register(&vexpress_reset_driver); +} +device_initcall(vexpress_reset_init); diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h index f1ed744..7b02341 100644 --- a/include/linux/vexpress.h +++ b/include/linux/vexpress.h @@ -117,4 +117,8 @@ int vexpress_config_read(struct vexpress_config_device *vecdev, int offset, int vexpress_config_write(struct vexpress_config_device *vecdev, int offset, u32 data); +/* Reset control */ +void vexpress_power_off(void); +void vexpress_restart(char str, const char *cmd); + #endif