Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp762689imm; Fri, 13 Jul 2018 06:02:55 -0700 (PDT) X-Google-Smtp-Source: AAOMgpd84gl9NvxRInbf0guF2NmWK0jKfLFg2UZIMVFbotPa1hzk6eHzJbCM+/liqqRG6YeKTpSR X-Received: by 2002:a17:902:301:: with SMTP id 1-v6mr6295545pld.127.1531486975720; Fri, 13 Jul 2018 06:02:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531486975; cv=none; d=google.com; s=arc-20160816; b=jeWVt4sLhrs7aO2pm3e3D2zSq/DcJiat6haYjJoXK70/HPt3nZmEoCboOCtLBra5lU i51Mmdv0HQ+hFdvg42ONvSZJ4/TXi58pg871d9IIFTV2g09rhSp5+nt5lGHKlZVQReNK WuY683HLGGgqaydFFSfGNOWSlDV2Cotj3jRP4TRZmmhmZTR1Q0kfreNr1jh+ab//t7zi XpIl9TDbl9K+YWNBeYtmmnLeykNMbTD28NzLEDYe7BtABGb5+ksWJuFA3cOOCQBzR225 IT4rey/uc/d6YxbkBn0gP0X1gkwIIYZUmpIShZKSFxy2JhBLzAKNjR3SvqFuJQqhePQ7 j6Gw== 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=alXrtZUNNIZtlyME5yZH93HBXTzITKbr00DshKKasMA=; b=DU9B09XHOeYXdnb4573qJtL3FZra68IL5yl8CuOLMV65wBh3mmj0808vqsc3757D1u SHNhyzcOuXeYTJV4JKDQHXyg9upfp1nq+ter/inOd+GdwBuPmSsSvGa8SNw9vaNzwpgI HL1nVvKOEVkBYtUEFyqgvz7sc4dZ0o1y3wG7kSd0Xt5McEW3wLDDNXIO4BITACr3tafS Ilfe26ZIgGKTtpTQ90CDr+sX85Jk2o0KfQ8lnxLrNKIdxJDVSVEA8LJnzuTICbcExqYU 99SfxjM9oK4TBa7fy0rwbjLB8DRcitwcDJplB1zNo8ihnsNp2vRgjUP5EjmUFng6kvai YuqQ== 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 g11-v6si21558725pgq.457.2018.07.13.06.02.39; Fri, 13 Jul 2018 06:02:55 -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 S1729781AbeGMNQ0 (ORCPT + 99 others); Fri, 13 Jul 2018 09:16:26 -0400 Received: from mx2.suse.de ([195.135.220.15]:38634 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729617AbeGMNQ0 (ORCPT ); Fri, 13 Jul 2018 09:16:26 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id F0B45AD3C; Fri, 13 Jul 2018 13:01:49 +0000 (UTC) From: Johannes Thumshirn To: Wim Van Sebroeck , Guenter Roeck Cc: linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org, Johannes Thumshirn Subject: [PATCH] watchdog: add driver for the MEN 16z069 IP-Core Date: Fri, 13 Jul 2018 14:58:31 +0200 Message-Id: <20180713125831.26074-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 --- MAINTAINERS | 6 ++ drivers/watchdog/Kconfig | 10 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/menz69_wdt.c | 175 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 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..9dccd8aabdb9 --- /dev/null +++ b/drivers/watchdog/menz69_wdt.c @@ -0,0 +1,175 @@ +// 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 + +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; + + if (val < MEN_Z069_WDT_COUNTER_MIN || val > MEN_Z069_WDT_COUNTER_MAX) + return -EINVAL; + + reg = readw(drv->base + MEN_Z069_WVR); + ena = reg & MEN_Z069_WTR_WDEN; + reg = ena | (val & MEN_Z069_WTR_WDET_MASK); + 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, + .min_timeout = 1, + .max_timeout = 65, +}; + +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; + + watchdog_init_timeout(&men_z069_wdt, 30, &dev->dev); + watchdog_set_nowayout(&men_z069_wdt, nowayout); + watchdog_set_drvdata(&men_z069_wdt, drv); + men_z069_wdt.parent = &dev->dev; + drv->wdt = men_z069_wdt; + mcb_set_drvdata(dev, drv); + + /* Set initial timeout to 65.5s and disable the watchdog */ + writew(MEN_Z069_WDT_COUNTER_MAX, drv->base + MEN_Z069_WTR); + + return watchdog_register_device(&men_z069_wdt); + +release_mem: + mcb_release_mem(mem); + return -ENXIO; +} + +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