Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp2046711imm; Mon, 16 Jul 2018 00:51:26 -0700 (PDT) X-Google-Smtp-Source: AAOMgpd5LkTyUCc7ZIXfDUyjQQhGiyAeUlDbFutwFeqKeIW6ek0+FoQ695DbNmifwqKCBrZTFv2k X-Received: by 2002:a17:902:22cc:: with SMTP id o12-v6mr15415020plg.68.1531727486579; Mon, 16 Jul 2018 00:51:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531727486; cv=none; d=google.com; s=arc-20160816; b=DzEu3jE/htuTjpudNdb+vGR6GjLJk52EsaGFy74Q5872GEiXhexzjh3j0F4RmXq6xV G6/1EQE1ejLYGEwpE5WGB7sZr5jTSjr7UGNa2+8631J558mxAprIEvN44puSp+RaTuKw KsiHw7vI1TkP/qfkIpnEuaaGigqX9HoK7FJkDiBLN0RWbqVs7/5F8XgQ+SLeke1WkPpf //52ZtFWRZHPzRCUcCeGPVLUFQTe7/PK6mWHcBrlaxRnZRBtfxFXlZgMmT+xFC2pN+ry EmTjsrd2BE3v8w9Yh9NIEXyb3iGL3WhxUQ0OHZMObq6Sn2Tgf0ug8ql04invWmMX9WbU 4Vag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=kZq0iRicEkljweEl12AnVR99xGnPXI6LzOvrc5SYdjg=; b=dPxl+2PZkE+tsZtn+Zo1/l2Ln5AKlMzv91QFXJBNFM6dUKNbmhnYdD9evnSbZZW+BX hpNvJDoNw6fjbNbByY32tiN5Lu54ieYlcXW06+GtCDIQ8ru2mllrcBkp7I5C/a0dPNr3 4DaFpooGe8ssAjoEL/wd3DPzNQhgd6X2fEy8pcF6p8EkWmyrlhm6vTUOcabBMwcvzU3x wIjXXTz+ZlOXpPdxK91xaWLy8axggJLoTPgG8fMTmO2JdAIRmC5kOzGiG61iaFNaNGh0 eBTqcV2BeN/3cQzLcyf7ClMmm2IU4Fq3QvxgJoa71089+RdE/iHae1SpTCxZHhBjV1gA 9NOg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m70-v6si33395934pfa.45.2018.07.16.00.51.12; Mon, 16 Jul 2018 00:51:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389138AbeGPIJs (ORCPT + 99 others); Mon, 16 Jul 2018 04:09:48 -0400 Received: from mx2.suse.de ([195.135.220.15]:41826 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2389117AbeGPIJr (ORCPT ); Mon, 16 Jul 2018 04:09:47 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D7E5FACC0; Mon, 16 Jul 2018 07:27:12 +0000 (UTC) From: Johannes Thumshirn To: Wim Van Sebroeck , Guenter Roeck Cc: linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, mmoese@suse.de, Johannes Thumshirn Subject: [PATCH v2] watchdog: add driver for the MEN 16z069 IP-Core Date: Mon, 16 Jul 2018 09:25:10 +0200 Message-Id: <20180716072510.6939-1-jthumshirn@suse.de> X-Mailer: git-send-email 2.16.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a driver for the MEN 16z069 Watchdog and Reset Controller IP-Core. Signed-off-by: Johannes Thumshirn --- Changes to v1: * Sorted includes alphabetically * Indented defines with tabs * Removed unnecessary timeout validation * Removed unnecessary masking of values * Fixed error return in .probe * Directly accessed drv->wdt * Removed leftover timeout resetting --- MAINTAINERS | 6 ++ drivers/watchdog/Kconfig | 10 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/menz69_wdt.c | 170 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 drivers/watchdog/menz69_wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 07d1576fc766..67a76f740294 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9298,6 +9298,12 @@ F: drivers/leds/leds-menf21bmc.c F: drivers/hwmon/menf21bmc_hwmon.c F: Documentation/hwmon/menf21bmc +MEN Z069 WATCHDOG DRIVER +M: Johannes Thumshirn +L: linux-watchdog@vger.kernel.org +S: Maintained +F: drivers/watchdog/menz069_wdt.c + MESON AO CEC DRIVER FOR AMLOGIC SOCS M: Neil Armstrong L: linux-media@lists.freedesktop.org diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9af07fd92763..df55d65bbb1c 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -161,6 +161,16 @@ config MENF21BMC_WATCHDOG This driver can also be built as a module. If so the module will be called menf21bmc_wdt. +config MENZ069_WATCHDOG + tristate "MEN 16Z069 Watchdog" + depends on MCB || COMPILE_TEST + select WATCHDOG_CORE + help + Say Y here to include support for the MEN 16Z069 Watchdog. + + This driver can also be built as a module. If so the module + will be called menz069_wdt. + config TANGOX_WATCHDOG tristate "Sigma Designs SMP86xx/SMP87xx watchdog" select WATCHDOG_CORE diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 1d3c6b094fe5..bf92e7bf9ce0 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -215,4 +215,5 @@ obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o +obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o diff --git a/drivers/watchdog/menz69_wdt.c b/drivers/watchdog/menz69_wdt.c new file mode 100644 index 000000000000..ed18238c5407 --- /dev/null +++ b/drivers/watchdog/menz69_wdt.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Watchdog driver for the MEN z069 IP-Core + * + * Copyright (C) 2018 Johannes Thumshirn + */ +#include +#include +#include +#include +#include + +struct men_z069_drv { + struct watchdog_device wdt; + void __iomem *base; + struct resource *mem; +}; + +#define MEN_Z069_WTR 0x10 +#define MEN_Z069_WTR_WDEN BIT(15) +#define MEN_Z069_WTR_WDET_MASK 0x7fff +#define MEN_Z069_WVR 0x14 + +#define MEN_Z069_TIMER_FREQ 500 /* 500 Hz */ +#define MEN_Z069_WDT_COUNTER_MIN 1 +#define MEN_Z069_WDT_COUNTER_MAX 0x7fff +#define MEN_Z069_DEFAULT_TIMEOUT 30 + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int men_z069_wdt_start(struct watchdog_device *wdt) +{ + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); + u16 val; + + val = readw(drv->base + MEN_Z069_WTR); + val |= MEN_Z069_WTR_WDEN; + writew(val, drv->base + MEN_Z069_WTR); + + return 0; +} + +static int men_z069_wdt_stop(struct watchdog_device *wdt) +{ + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); + u16 val; + + val = readw(drv->base + MEN_Z069_WTR); + val &= ~MEN_Z069_WTR_WDEN; + writew(val, drv->base + MEN_Z069_WTR); + + return 0; +} + +static int men_z069_wdt_ping(struct watchdog_device *wdt) +{ + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); + u16 val; + + /* The watchdog trigger value toggles between 0x5555 and 0xaaaa */ + val = readw(drv->base + MEN_Z069_WVR); + val ^= 0xffff; + writew(val, drv->base + MEN_Z069_WVR); + + return 0; +} + +static int men_z069_wdt_set_timeout(struct watchdog_device *wdt, + unsigned int timeout) +{ + struct men_z069_drv *drv = watchdog_get_drvdata(wdt); + u16 reg, val, ena; + + wdt->timeout = timeout; + val = timeout * MEN_Z069_TIMER_FREQ; + + reg = readw(drv->base + MEN_Z069_WVR); + ena = reg & MEN_Z069_WTR_WDEN; + reg = ena | val; + writew(reg, drv->base + MEN_Z069_WTR); + + return 0; +} + +static const struct watchdog_info men_z069_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "MEN z069 Watchdog", +}; + +static const struct watchdog_ops men_z069_ops = { + .owner = THIS_MODULE, + .start = men_z069_wdt_start, + .stop = men_z069_wdt_stop, + .ping = men_z069_wdt_ping, + .set_timeout = men_z069_wdt_set_timeout, +}; + +static struct watchdog_device men_z069_wdt = { + .info = &men_z069_info, + .ops = &men_z069_ops, + .timeout = MEN_Z069_DEFAULT_TIMEOUT, + .min_timeout = 1, + .max_timeout = MEN_Z069_WDT_COUNTER_MAX / MEN_Z069_TIMER_FREQ, +}; + +static int men_z069_probe(struct mcb_device *dev, + const struct mcb_device_id *id) +{ + struct men_z069_drv *drv; + struct resource *mem; + + drv = devm_kzalloc(&dev->dev, sizeof(struct men_z069_drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + mem = mcb_request_mem(dev, "z069-wdt"); + if (IS_ERR(mem)) + return PTR_ERR(mem); + + drv->base = devm_ioremap(&dev->dev, mem->start, resource_size(mem)); + if (drv->base == NULL) + goto release_mem; + + drv->mem = mem; + + drv->wdt = men_z069_wdt; + watchdog_init_timeout(&drv->wdt, 0, &dev->dev); + watchdog_set_nowayout(&drv->wdt, nowayout); + watchdog_set_drvdata(&drv->wdt, drv); + drv->wdt.parent = &dev->dev; + mcb_set_drvdata(dev, drv); + + return watchdog_register_device(&men_z069_wdt); + +release_mem: + mcb_release_mem(mem); + return -ENOMEM; +} + +static void men_z069_remove(struct mcb_device *dev) +{ + struct men_z069_drv *drv = mcb_get_drvdata(dev); + + watchdog_unregister_device(&drv->wdt); + mcb_release_mem(drv->mem); +} + +static const struct mcb_device_id men_z069_ids[] = { + { .device = 0x45 }, + { } +}; +MODULE_DEVICE_TABLE(mcb, men_z069_ids); + +static struct mcb_driver men_z069_driver = { + .driver = { + .name = "z069-wdt", + .owner = THIS_MODULE, + }, + .probe = men_z069_probe, + .remove = men_z069_remove, + .id_table = men_z069_ids, +}; +module_mcb_driver(men_z069_driver); + +MODULE_AUTHOR("Johannes Thumshirn "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("mcb:16z069"); -- 2.16.4