From patchwork Mon Sep 4 23:16:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andreas_F=C3=A4rber?= X-Patchwork-Id: 111621 Delivered-To: patch@linaro.org Received: by 10.140.94.166 with SMTP id g35csp2096329qge; Mon, 4 Sep 2017 16:16:13 -0700 (PDT) X-Google-Smtp-Source: ADKCNb5/odaZgmkUNDBINz7XYo2e+qcyX5o/Q4hNA056+9fC0nvQJQ4TejP1iUBZH7WfiWgdu0Ov X-Received: by 10.98.138.88 with SMTP id y85mr1835886pfd.224.1504566973584; Mon, 04 Sep 2017 16:16:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1504566973; cv=none; d=google.com; s=arc-20160816; b=lMrsiRqtSGGy/wWPOfh1hmgKiamTVgs3rRQkCua/5vcLygvebCVR8a6r3bicb8aTnP afVv+7FHeYd9/n8VwVt80x/OLeOANqM3fTMQS9lc6te2E2WGs3QwpaUxCajxBh3cUnUH Xk8alHuKMIt6zL6s3i5rQL3n9hnXbMrfh7qKR8GhzGajC4EsKBDH7ckuB2DofTl5i8y5 cV0NzzoUCUvH6urotBuhJbO7FurhTm5PwQIy3/2sEGu4uVAYMj8tk1ec6i+Gl8Ffwhpw MR0YRwm+jmUB7j/0AHsAKJKBbSSd12JGdh+gInHzieLXc7RSJVw4TiTWKM0oF/w/Fjh9 Qdmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=jvDSD3LJw55EovRM4YrrgFK6OB+9aJBgLDMRiDUlaZs=; b=moeCVgpbPidVWNzML5WhcLbHX33rCGtgBmoD/XObrUmEFFdUYOy8NSPwe8xJdBB+rc dbMUxuRGszxr/8I+lXj8vkx6dpQjwdjxdcNfrS5+i9PXG4AJNix/cH6jzjab5OZKW3Cd KucCCsmmIQfoJGG9UZq9o+cifOp28pv5YLyvSgEIp0c7MO8hRGv8esD2/WFeBR4Q+enH 27GRsCp0Qx26pIBEPFRm+9JbJJs23TFVAEKMmWtEX57P05B6RaR7NmRtjQwYNdzAOamR g6qrs3KDBV5OpglkfKLupQol8ETj5eCO28eDYDikoViYRp2q1kA9BQNxG7sQ+gx1rDqn qdvQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-watchdog-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-watchdog-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 e32si6083490plb.498.2017.09.04.16.16.13 for ; Mon, 04 Sep 2017 16:16:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-watchdog-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-watchdog-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-watchdog-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754045AbdIDXQM (ORCPT ); Mon, 4 Sep 2017 19:16:12 -0400 Received: from mx2.suse.de ([195.135.220.15]:39406 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754007AbdIDXQI (ORCPT ); Mon, 4 Sep 2017 19:16:08 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 4D60BABDB; Mon, 4 Sep 2017 23:16:07 +0000 (UTC) From: =?utf-8?q?Andreas_F=C3=A4rber?= To: Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Roc He , =?utf-8?b?6JKL?= =?utf-8?b?5Li955C0?= , =?utf-8?q?Andreas_F=C3=A4rber?= Subject: [PATCH v2 2/3] watchdog: Add Realtek RTD1295 Date: Tue, 5 Sep 2017 01:16:01 +0200 Message-Id: <20170904231602.29787-3-afaerber@suse.de> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170904231602.29787-1-afaerber@suse.de> References: <20170904231602.29787-1-afaerber@suse.de> MIME-Version: 1.0 Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org Add a watchdog driver for the Realtek RTD1295 SoC. Based on QNAP's arch/arm/mach-rtk119x/driver/rtk_watchdog.c code and mach-rtk119x/driver/dc2vo/fpga/include/iso_reg.h register defines. Signed-off-by: Andreas Färber --- v1 -> v2: * Added explicit include of bitops.h (Guenther) * Set timeout field in set_timeout (Guenther) * Implemented remove (Guenther) * Replaced remaining hardcoded frequency with clk_get_rate() drivers/watchdog/Kconfig | 10 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rtd119x_wdt.c | 168 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 drivers/watchdog/rtd119x_wdt.c -- 2.13.5 -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-by: Guenter Roeck diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbfdc7e6..8fa81518c3fa 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -787,6 +787,16 @@ config UNIPHIER_WATCHDOG To compile this driver as a module, choose M here: the module will be called uniphier_wdt. +config RTD119X_WATCHDOG + bool "Realtek RTD119x/RTD129x watchdog support" + depends on ARCH_REALTEK || COMPILE_TEST + depends on OF + select WATCHDOG_CORE + default ARCH_REALTEK + help + Say Y here to include support for the watchdog timer in + Realtek RTD1295 SoCs. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 56adf9fa67d0..63cb3ed8117d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o +obj-$(CONFIG_RTD119X_WATCHDOG) += rtd119x_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/rtd119x_wdt.c b/drivers/watchdog/rtd119x_wdt.c new file mode 100644 index 000000000000..d001c17ddfde --- /dev/null +++ b/drivers/watchdog/rtd119x_wdt.c @@ -0,0 +1,168 @@ +/* + * Realtek RTD129x watchdog + * + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTD119X_TCWCR 0x0 +#define RTD119X_TCWTR 0x4 +#define RTD119X_TCWOV 0xc + +#define RTD119X_TCWCR_WDEN_DISABLED 0xa5 +#define RTD119X_TCWCR_WDEN_ENABLED 0xff +#define RTD119X_TCWCR_WDEN_MASK 0xff + +#define RTD119X_TCWTR_WDCLR BIT(0) + +struct rtd119x_watchdog_device { + struct watchdog_device wdt_dev; + void __iomem *base; + struct clk *clk; +}; + +static int rtd119x_wdt_start(struct watchdog_device *wdev) +{ + struct rtd119x_watchdog_device *data = watchdog_get_drvdata(wdev); + u32 val; + + val = readl_relaxed(data->base + RTD119X_TCWCR); + val &= ~RTD119X_TCWCR_WDEN_MASK; + val |= RTD119X_TCWCR_WDEN_ENABLED; + writel(val, data->base + RTD119X_TCWCR); + + return 0; +} + +static int rtd119x_wdt_stop(struct watchdog_device *wdev) +{ + struct rtd119x_watchdog_device *data = watchdog_get_drvdata(wdev); + u32 val; + + val = readl_relaxed(data->base + RTD119X_TCWCR); + val &= ~RTD119X_TCWCR_WDEN_MASK; + val |= RTD119X_TCWCR_WDEN_DISABLED; + writel(val, data->base + RTD119X_TCWCR); + + return 0; +} + +static int rtd119x_wdt_ping(struct watchdog_device *wdev) +{ + struct rtd119x_watchdog_device *data = watchdog_get_drvdata(wdev); + + writel_relaxed(RTD119X_TCWTR_WDCLR, data->base + RTD119X_TCWTR); + + return rtd119x_wdt_start(wdev); +} + +static int rtd119x_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val) +{ + struct rtd119x_watchdog_device *data = watchdog_get_drvdata(wdev); + + writel(val * clk_get_rate(data->clk), data->base + RTD119X_TCWOV); + + data->wdt_dev.timeout = val; + + return 0; +} + +static const struct watchdog_ops rtd119x_wdt_ops = { + .owner = THIS_MODULE, + .start = rtd119x_wdt_start, + .stop = rtd119x_wdt_stop, + .ping = rtd119x_wdt_ping, + .set_timeout = rtd119x_wdt_set_timeout, +}; + +static const struct watchdog_info rtd119x_wdt_info = { + .identity = "rtd119x-wdt", + .options = 0, +}; + +static const struct of_device_id rtd119x_wdt_dt_ids[] = { + { .compatible = "realtek,rtd1295-watchdog" }, + { } +}; + +static int rtd119x_wdt_probe(struct platform_device *pdev) +{ + struct rtd119x_watchdog_device *data; + struct resource *res; + int ret; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->base)) + return PTR_ERR(data->base); + + data->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(data->clk)) + return PTR_ERR(data->clk); + + ret = clk_prepare_enable(data->clk); + if (ret) { + clk_put(data->clk); + return ret; + } + + data->wdt_dev.info = &rtd119x_wdt_info; + data->wdt_dev.ops = &rtd119x_wdt_ops; + data->wdt_dev.timeout = 120; + data->wdt_dev.max_timeout = 0xffffffff / clk_get_rate(data->clk); + data->wdt_dev.min_timeout = 1; + data->wdt_dev.parent = &pdev->dev; + + watchdog_stop_on_reboot(&data->wdt_dev); + watchdog_set_drvdata(&data->wdt_dev, data); + platform_set_drvdata(pdev, data); + + writel_relaxed(RTD119X_TCWTR_WDCLR, data->base + RTD119X_TCWTR); + rtd119x_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout); + rtd119x_wdt_stop(&data->wdt_dev); + + ret = devm_watchdog_register_device(&pdev->dev, &data->wdt_dev); + if (ret) { + clk_disable_unprepare(data->clk); + clk_put(data->clk); + return ret; + } + + return 0; +} + +static int rtd119x_wdt_remove(struct platform_device *pdev) +{ + struct rtd119x_watchdog_device *data = platform_get_drvdata(pdev); + + watchdog_unregister_device(&data->wdt_dev); + + clk_disable_unprepare(data->clk); + clk_put(data->clk); + + return 0; +} + +static struct platform_driver rtd119x_wdt_driver = { + .probe = rtd119x_wdt_probe, + .remove = rtd119x_wdt_remove, + .driver = { + .name = "rtd1295-watchdog", + .of_match_table = rtd119x_wdt_dt_ids, + }, +}; +builtin_platform_driver(rtd119x_wdt_driver);