[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

STALE3252d

Revision v1 of 5 in this series.

38 messages, 5 authors, 2017-10-12 · open the first message on its own page

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:07

The MOXA ART and Aspeed watchdogs are clearly based on the
Faraday Technology FTWDT010 IP block.

This series consolidates the drivers into one by extending
the Gemini driver to be as generic as possible, renaming it
to ftwdt010_wdt and merging the two other drivers into it.

As similar approach was used for the FTTMR010 driver in the
past.

The series ends with two patches that will be applied to
the ARM SoC tree to fix up the PCLK annotations, but these
are not needed to make the consolidation, patches 1-9 can
be applied directly to the watchdog tree to perform the
consolidation.

Obviously I would like the MOXA ART and Aspeed maintainers
to test the series to see that it still works as expected for
them afterwards.

The patch series is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
Branch ftwdt010

Linus Walleij (11):
  watchdog: gemini/ftwdt010: rename DT bindings
  watchdog: gemini/ftwdt010: rename driver and symbols
  watchdog: ftwdt010: Make interrupt optional
  watchdog: ftwdt010: Add clock support
  watchdog: ftwdt010: Add restart support
  watchdog: ftwdt010: Extend DT bindings to derivatives
  watchdog: ftwdt010: Delete surplus bindings
  watchdog: ftwdt010/moxart: Merge MOXA ART into FTWDT010
  watchdog: ftwdt010/aspeed: Merge Aspeed into FTWDT010
  ARM: dts: fix PCLK name on Gemini and MOXA ART
  ARM: dts: Add PCLK to the Aspeed watchdogs

 .../devicetree/bindings/watchdog/aspeed-wdt.txt    |  16 -
 .../bindings/watchdog/cortina,gemin-watchdog.txt   |  17 --
 .../bindings/watchdog/cortina,gemini-watchdog.txt  |  17 --
 .../bindings/watchdog/faraday,ftwdt010.txt         |  34 +++
 .../bindings/watchdog/moxa,moxart-watchdog.txt     |  15 -
 arch/arm/boot/dts/aspeed-g4.dtsi                   |   7 +-
 arch/arm/boot/dts/aspeed-g5.dtsi                   |  12 +-
 arch/arm/boot/dts/gemini.dtsi                      |   3 +-
 arch/arm/boot/dts/moxart.dtsi                      |   3 +-
 drivers/watchdog/Kconfig                           |  39 +--
 drivers/watchdog/Makefile                          |   4 +-
 drivers/watchdog/aspeed_wdt.c                      | 200 ------------
 drivers/watchdog/ftwdt010_wdt.c                    | 338 +++++++++++++++++++++
 drivers/watchdog/gemini_wdt.c                      | 229 --------------
 drivers/watchdog/moxart_wdt.c                      | 178 -----------
 15 files changed, 401 insertions(+), 711 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
 delete mode 100644 Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt
 delete mode 100644 Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt
 create mode 100644 Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt
 delete mode 100644 Documentation/devicetree/bindings/watchdog/moxa,moxart-watchdog.txt
 delete mode 100644 drivers/watchdog/aspeed_wdt.c
 create mode 100644 drivers/watchdog/ftwdt010_wdt.c
 delete mode 100644 drivers/watchdog/gemini_wdt.c
 delete mode 100644 drivers/watchdog/moxart_wdt.c

-- 
2.13.4

[PATCH 02/11] watchdog: gemini/ftwdt010: rename driver and symbols

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:09

This renames all the driver files and symbols for the Gemini
watchdog to FTWDT010 as it has been revealed that this IP block
is a generic watchdog timer from Faraday Technology used in
several SoC designs.

Select thid driver by default for the Gemini, it is a sensible
driver to always have enabled.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig                          |  14 +--
 drivers/watchdog/Makefile                         |   2 +-
 drivers/watchdog/{gemini_wdt.c => ftwdt010_wdt.c} | 117 +++++++++++-----------
 3 files changed, 68 insertions(+), 65 deletions(-)
 rename drivers/watchdog/{gemini_wdt.c => ftwdt010_wdt.c} (50%)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c722cbfdc7e6..fd44a542036a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -321,16 +321,18 @@ config 977_WATCHDOG
 
 	  Not sure? It's safe to say N.
 
-config GEMINI_WATCHDOG
-	tristate "Gemini watchdog"
-	depends on ARCH_GEMINI
+config FTWDT010_WATCHDOG
+	tristate "Faraday Technology FTWDT010 watchdog"
+	depends on ARM || COMPILE_TEST
 	select WATCHDOG_CORE
+	default ARCH_GEMINI
 	help
-	  Say Y here if to include support for the watchdog timer
-	  embedded in the Cortina Systems Gemini family of devices.
+	  Say Y here if to include support for the Faraday Technology
+	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
+	  family of devices.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called gemini_wdt.
+	  module will be called ftwdt010_wdt.
 
 config IXP4XX_WATCHDOG
 	tristate "IXP4xx Watchdog"
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 56adf9fa67d0..df91d7db821c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_GEMINI_WATCHDOG) += gemini_wdt.o
+obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
diff --git a/drivers/watchdog/gemini_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
similarity index 50%
rename from drivers/watchdog/gemini_wdt.c
rename to drivers/watchdog/ftwdt010_wdt.c
index 8155aa619e4c..637ffd812f0b 100644
--- a/drivers/watchdog/gemini_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -1,5 +1,5 @@
 /*
- * Watchdog driver for Cortina Systems Gemini SoC
+ * Watchdog driver for Faraday Technology FTWDT010
  *
  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  *
@@ -22,10 +22,10 @@
 #include <linux/slab.h>
 #include <linux/watchdog.h>
 
-#define GEMINI_WDCOUNTER	0x0
-#define GEMINI_WDLOAD		0x4
-#define GEMINI_WDRESTART	0x8
-#define GEMINI_WDCR		0xC
+#define FTWDT010_WDCOUNTER	0x0
+#define FTWDT010_WDLOAD		0x4
+#define FTWDT010_WDRESTART	0x8
+#define FTWDT010_WDCR		0xC
 
 #define WDRESTART_MAGIC		0x5AB9
 
@@ -35,79 +35,79 @@
 
 #define WDT_CLOCK		5000000		/* 5 MHz */
 
-struct gemini_wdt {
+struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
 };
 
 static inline
-struct gemini_wdt *to_gemini_wdt(struct watchdog_device *wdd)
+struct ftwdt010_wdt *to_ftwdt010_wdt(struct watchdog_device *wdd)
 {
-	return container_of(wdd, struct gemini_wdt, wdd);
+	return container_of(wdd, struct ftwdt010_wdt, wdd);
 }
 
-static int gemini_wdt_start(struct watchdog_device *wdd)
+static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(wdd->timeout * WDT_CLOCK, gwdt->base + GEMINI_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + GEMINI_WDRESTART);
+	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
+	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
 	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
-			gwdt->base + GEMINI_WDCR);
+			gwdt->base + FTWDT010_WDCR);
 	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
-			gwdt->base + GEMINI_WDCR);
+			gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int gemini_wdt_stop(struct watchdog_device *wdd)
+static int ftwdt010_wdt_stop(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(0, gwdt->base + GEMINI_WDCR);
+	writel(0, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int gemini_wdt_ping(struct watchdog_device *wdd)
+static int ftwdt010_wdt_ping(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(WDRESTART_MAGIC, gwdt->base + GEMINI_WDRESTART);
+	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 
 	return 0;
 }
 
-static int gemini_wdt_set_timeout(struct watchdog_device *wdd,
+static int ftwdt010_wdt_set_timeout(struct watchdog_device *wdd,
 				  unsigned int timeout)
 {
 	wdd->timeout = timeout;
 	if (watchdog_active(wdd))
-		gemini_wdt_start(wdd);
+		ftwdt010_wdt_start(wdd);
 
 	return 0;
 }
 
-static irqreturn_t gemini_wdt_interrupt(int irq, void *data)
+static irqreturn_t ftwdt010_wdt_interrupt(int irq, void *data)
 {
-	struct gemini_wdt *gwdt = data;
+	struct ftwdt010_wdt *gwdt = data;
 
 	watchdog_notify_pretimeout(&gwdt->wdd);
 
 	return IRQ_HANDLED;
 }
 
-static const struct watchdog_ops gemini_wdt_ops = {
-	.start		= gemini_wdt_start,
-	.stop		= gemini_wdt_stop,
-	.ping		= gemini_wdt_ping,
-	.set_timeout	= gemini_wdt_set_timeout,
+static const struct watchdog_ops ftwdt010_wdt_ops = {
+	.start		= ftwdt010_wdt_start,
+	.stop		= ftwdt010_wdt_stop,
+	.ping		= ftwdt010_wdt_ping,
+	.set_timeout	= ftwdt010_wdt_set_timeout,
 	.owner		= THIS_MODULE,
 };
 
-static const struct watchdog_info gemini_wdt_info = {
+static const struct watchdog_info ftwdt010_wdt_info = {
 	.options	= WDIOF_KEEPALIVEPING
 			| WDIOF_MAGICCLOSE
 			| WDIOF_SETTIMEOUT,
@@ -115,11 +115,11 @@ static const struct watchdog_info gemini_wdt_info = {
 };
 
 
-static int gemini_wdt_probe(struct platform_device *pdev)
+static int ftwdt010_wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
-	struct gemini_wdt *gwdt;
+	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
 	int irq;
 	int ret;
@@ -138,8 +138,8 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	gwdt->dev = dev;
-	gwdt->wdd.info = &gemini_wdt_info;
-	gwdt->wdd.ops = &gemini_wdt_ops;
+	gwdt->wdd.info = &ftwdt010_wdt_info;
+	gwdt->wdd.ops = &ftwdt010_wdt_ops;
 	gwdt->wdd.min_timeout = 1;
 	gwdt->wdd.max_timeout = 0xFFFFFFFF / WDT_CLOCK;
 	gwdt->wdd.parent = dev;
@@ -151,14 +151,14 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 	gwdt->wdd.timeout = 13U;
 	watchdog_init_timeout(&gwdt->wdd, 0, dev);
 
-	reg = readw(gwdt->base + GEMINI_WDCR);
+	reg = readw(gwdt->base + FTWDT010_WDCR);
 	if (reg & WDCR_ENABLE) {
 		/* Watchdog was enabled by the bootloader, disable it. */
 		reg &= ~WDCR_ENABLE;
-		writel(reg, gwdt->base + GEMINI_WDCR);
+		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
-	ret = devm_request_irq(dev, irq, gemini_wdt_interrupt, 0,
+	ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
 			       "watchdog bark", gwdt);
 	if (ret)
 		return ret;
@@ -171,59 +171,60 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, gwdt);
-	dev_info(dev, "Gemini watchdog driver enabled\n");
+	dev_info(dev, "FTWDT010 watchdog driver enabled\n");
 
 	return 0;
 }
 
-static int __maybe_unused gemini_wdt_suspend(struct device *dev)
+static int __maybe_unused ftwdt010_wdt_suspend(struct device *dev)
 {
-	struct gemini_wdt *gwdt = dev_get_drvdata(dev);
+	struct ftwdt010_wdt *gwdt = dev_get_drvdata(dev);
 	unsigned int reg;
 
-	reg = readw(gwdt->base + GEMINI_WDCR);
+	reg = readw(gwdt->base + FTWDT010_WDCR);
 	reg &= ~WDCR_ENABLE;
-	writel(reg, gwdt->base + GEMINI_WDCR);
+	writel(reg, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int __maybe_unused gemini_wdt_resume(struct device *dev)
+static int __maybe_unused ftwdt010_wdt_resume(struct device *dev)
 {
-	struct gemini_wdt *gwdt = dev_get_drvdata(dev);
+	struct ftwdt010_wdt *gwdt = dev_get_drvdata(dev);
 	unsigned int reg;
 
 	if (watchdog_active(&gwdt->wdd)) {
-		reg = readw(gwdt->base + GEMINI_WDCR);
+		reg = readw(gwdt->base + FTWDT010_WDCR);
 		reg |= WDCR_ENABLE;
-		writel(reg, gwdt->base + GEMINI_WDCR);
+		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
 	return 0;
 }
 
-static const struct dev_pm_ops gemini_wdt_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(gemini_wdt_suspend,
-				gemini_wdt_resume)
+static const struct dev_pm_ops ftwdt010_wdt_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ftwdt010_wdt_suspend,
+				ftwdt010_wdt_resume)
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id gemini_wdt_match[] = {
+static const struct of_device_id ftwdt010_wdt_match[] = {
+	{ .compatible = "faraday,ftwdt010" },
 	{ .compatible = "cortina,gemini-watchdog" },
 	{},
 };
-MODULE_DEVICE_TABLE(of, gemini_wdt_match);
+MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
 #endif
 
-static struct platform_driver gemini_wdt_driver = {
-	.probe		= gemini_wdt_probe,
+static struct platform_driver ftwdt010_wdt_driver = {
+	.probe		= ftwdt010_wdt_probe,
 	.driver		= {
-		.name	= "gemini-wdt",
-		.of_match_table = of_match_ptr(gemini_wdt_match),
-		.pm = &gemini_wdt_dev_pm_ops,
+		.name	= "ftwdt010-wdt",
+		.of_match_table = of_match_ptr(ftwdt010_wdt_match),
+		.pm = &ftwdt010_wdt_dev_pm_ops,
 	},
 };
-module_platform_driver(gemini_wdt_driver);
+module_platform_driver(ftwdt010_wdt_driver);
 MODULE_AUTHOR("Linus Walleij");
-MODULE_DESCRIPTION("Watchdog driver for Gemini");
+MODULE_DESCRIPTION("Watchdog driver for Faraday Technology FTWDT010");
 MODULE_LICENSE("GPL");
-- 
2.13.4

[PATCH 03/11] watchdog: ftwdt010: Make interrupt optional

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:10

The Moxart does not appear to be using the interrupt from the
watchdog timer, maybe it's not even routed, so as to support
more architectures with this driver, make the interrupt
optional.

While we are at it: actually enable the use of the interrupt
if present by setting the right bit in the control register
and define the missing control register bits.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/ftwdt010_wdt.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 637ffd812f0b..ab38a3a89300 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -30,6 +30,8 @@
 #define WDRESTART_MAGIC		0x5AB9
 
 #define WDCR_CLOCK_5MHZ		BIT(4)
+#define WDCR_WDEXT		BIT(3)
+#define WDCR_WDINTR		BIT(2)
 #define WDCR_SYS_RST		BIT(1)
 #define WDCR_ENABLE		BIT(0)
 
@@ -39,6 +41,7 @@ struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
+	bool			has_irq;
 };
 
 static inline
@@ -50,14 +53,18 @@ struct ftwdt010_wdt *to_ftwdt010_wdt(struct watchdog_device *wdd)
 static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 {
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
+	u32 enable;
 
 	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
 	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
-	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
-			gwdt->base + FTWDT010_WDCR);
-	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
-			gwdt->base + FTWDT010_WDCR);
+	enable = WDCR_CLOCK_5MHZ | WDCR_SYS_RST;
+	writel(enable, gwdt->base + FTWDT010_WDCR);
+	enable |= WDCR_CLOCK_5MHZ;
+	if (gwdt->has_irq)
+		enable |= WDCR_WDINTR;
+	enable |= WDCR_ENABLE;
+	writel(enable, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
@@ -133,10 +140,6 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	if (IS_ERR(gwdt->base))
 		return PTR_ERR(gwdt->base);
 
-	irq = platform_get_irq(pdev, 0);
-	if (!irq)
-		return -EINVAL;
-
 	gwdt->dev = dev;
 	gwdt->wdd.info = &ftwdt010_wdt_info;
 	gwdt->wdd.ops = &ftwdt010_wdt_ops;
@@ -158,10 +161,14 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
-	ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
-			       "watchdog bark", gwdt);
-	if (ret)
-		return ret;
+	irq = platform_get_irq(pdev, 0);
+	if (irq) {
+		ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
+				       "watchdog bark", gwdt);
+		if (ret)
+			return ret;
+		gwdt->has_irq = true;
+	}
 
 	ret = devm_watchdog_register_device(dev, &gwdt->wdd);
 	if (ret) {
-- 
2.13.4

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:11

The Gemini platform now provides a proper clock look-up for this
and other IPs, so add clock support to the driver. This also aids
in using the same driver with other platforms such as MOXA ART.

The IP has two clock inputs: PCLK (the IP peripheral clock) and
EXTCLK (an external clock). We are a bit elaborate around this:
on Gemini the EXTCLK is used by default today and it's 5MHz, and
on MOXA ART the PCLK is used. On Aspeed the EXTCLK is used and
it's 1MHz. So add some clever code to fall back to platform
defaults if PCLK or EXTCLK is not provided by the device tree.

Take this opportnity to implement .remove() for the driver that
stops the watchdog and disables the clocks.

Add credits that this code is inspired by MOXA ART.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/ftwdt010_wdt.c | 79 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 8 deletions(-)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index ab38a3a89300..680279f5c679 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -5,6 +5,8 @@
  *
  * Inspired by the out-of-tree drivers from OpenWRT:
  * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ * Inspired by the MOXA ART driver from Jonas Jensen:
+ * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
  *
  * 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
@@ -18,9 +20,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/watchdog.h>
+#include <linux/clk.h>
 
 #define FTWDT010_WDCOUNTER	0x0
 #define FTWDT010_WDLOAD		0x4
@@ -29,19 +33,21 @@
 
 #define WDRESTART_MAGIC		0x5AB9
 
-#define WDCR_CLOCK_5MHZ		BIT(4)
+#define WDCR_EXTCLK		BIT(4)
 #define WDCR_WDEXT		BIT(3)
 #define WDCR_WDINTR		BIT(2)
 #define WDCR_SYS_RST		BIT(1)
 #define WDCR_ENABLE		BIT(0)
 
-#define WDT_CLOCK		5000000		/* 5 MHz */
-
 struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
 	bool			has_irq;
+	struct clk		*pclk;
+	struct clk		*extclk;
+	unsigned int		clk_freq;
+	bool			use_extclk;
 };
 
 static inline
@@ -55,12 +61,13 @@ static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 	u32 enable;
 
-	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
+	writel(wdd->timeout * gwdt->clk_freq, gwdt->base + FTWDT010_WDLOAD);
 	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
-	enable = WDCR_CLOCK_5MHZ | WDCR_SYS_RST;
+	enable = WDCR_SYS_RST;
+	if (gwdt->use_extclk)
+		enable |= WDCR_EXTCLK;
 	writel(enable, gwdt->base + FTWDT010_WDCR);
-	enable |= WDCR_CLOCK_5MHZ;
 	if (gwdt->has_irq)
 		enable |= WDCR_WDINTR;
 	enable |= WDCR_ENABLE;
@@ -125,6 +132,7 @@ static const struct watchdog_info ftwdt010_wdt_info = {
 static int ftwdt010_wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 	struct resource *res;
 	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
@@ -140,11 +148,51 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	if (IS_ERR(gwdt->base))
 		return PTR_ERR(gwdt->base);
 
+	gwdt->use_extclk = of_property_read_bool(np, "faraday,use-extclk");
+
+	gwdt->pclk = devm_clk_get(dev, "PCLK");
+	if (!IS_ERR(gwdt->pclk)) {
+		ret = clk_prepare_enable(gwdt->pclk);
+		if (ret) {
+			dev_err(&pdev->dev, "unable to enable PCLK\n");
+			return ret;
+		}
+		if (!gwdt->use_extclk)
+			gwdt->clk_freq = clk_get_rate(gwdt->pclk);
+	} else {
+		dev_info(dev, "PCLK clock not found assume always-on\n");
+	}
+
+	gwdt->extclk = devm_clk_get(dev, "EXTCLK");
+	if (!IS_ERR(gwdt->extclk)) {
+		/* Only enable and get frequency from EXTCLK if it's in use */
+		if (gwdt->use_extclk) {
+			ret = clk_prepare_enable(gwdt->extclk);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"unable to enable EXTCLK\n");
+				return ret;
+			}
+			gwdt->clk_freq = clk_get_rate(gwdt->extclk);
+		}
+	} else {
+		if (of_device_is_compatible(np, "cortina,gemini-watchdog")) {
+			gwdt->clk_freq = 5000000;
+			gwdt->use_extclk = true;
+			dev_info(dev, "assume 5MHz EXTCLK on Gemini\n");
+		}
+	}
+
+	if (gwdt->clk_freq == 0) {
+		dev_err(dev, "no clocking available\n");
+		return -EINVAL;
+	}
+
 	gwdt->dev = dev;
 	gwdt->wdd.info = &ftwdt010_wdt_info;
 	gwdt->wdd.ops = &ftwdt010_wdt_ops;
 	gwdt->wdd.min_timeout = 1;
-	gwdt->wdd.max_timeout = 0xFFFFFFFF / WDT_CLOCK;
+	gwdt->wdd.max_timeout = UINT_MAX / gwdt->clk_freq;
 	gwdt->wdd.parent = dev;
 
 	/*
@@ -178,7 +226,21 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, gwdt);
-	dev_info(dev, "FTWDT010 watchdog driver enabled\n");
+	dev_info(dev, "FTWDT010 watchdog driver @%uHz\n",
+		 gwdt->clk_freq);
+
+	return 0;
+}
+
+static int ftwdt010_wdt_remove(struct platform_device *pdev)
+{
+	struct ftwdt010_wdt *gwdt = platform_get_drvdata(pdev);
+
+	writel(0, gwdt->base + FTWDT010_WDCR);
+	if (!IS_ERR(gwdt->pclk))
+		clk_disable_unprepare(gwdt->pclk);
+	if (!IS_ERR(gwdt->extclk) && gwdt->use_extclk)
+		clk_disable_unprepare(gwdt->extclk);
 
 	return 0;
 }
@@ -225,6 +287,7 @@ MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
 
 static struct platform_driver ftwdt010_wdt_driver = {
 	.probe		= ftwdt010_wdt_probe,
+	.remove		= ftwdt010_wdt_remove,
 	.driver		= {
 		.name	= "ftwdt010-wdt",
 		.of_match_table = of_match_ptr(ftwdt010_wdt_match),
-- 
2.13.4

[PATCH 05/11] watchdog: ftwdt010: Add restart support

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:12

This enables the Faraday FTWDT010 to restart the system,
if need be. Set the restart priority for the watchdog to
128.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/ftwdt010_wdt.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 680279f5c679..7fc865eea28d 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -56,6 +56,22 @@ struct ftwdt010_wdt *to_ftwdt010_wdt(struct watchdog_device *wdd)
 	return container_of(wdd, struct ftwdt010_wdt, wdd);
 }
 
+static int ftwdt010_wdt_restart(struct watchdog_device *wdd,
+				unsigned long action, void *data)
+{
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
+	u32 enable;
+
+	writel(1, gwdt->base + FTWDT010_WDLOAD);
+	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	enable = WDCR_SYS_RST | WDCR_ENABLE;
+	if (gwdt->use_extclk)
+		enable |= WDCR_EXTCLK;
+	writel(enable, gwdt->base + FTWDT010_WDCR);
+
+	return 0;
+}
+
 static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 {
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
@@ -118,6 +134,7 @@ static const struct watchdog_ops ftwdt010_wdt_ops = {
 	.stop		= ftwdt010_wdt_stop,
 	.ping		= ftwdt010_wdt_ping,
 	.set_timeout	= ftwdt010_wdt_set_timeout,
+	.restart	= ftwdt010_wdt_restart,
 	.owner		= THIS_MODULE,
 };
 
@@ -201,6 +218,7 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	 */
 	gwdt->wdd.timeout = 13U;
 	watchdog_init_timeout(&gwdt->wdd, 0, dev);
+	watchdog_set_restart_priority(&gwdt->wdd, 128);
 
 	reg = readw(gwdt->base + FTWDT010_WDCR);
 	if (reg & WDCR_ENABLE) {
-- 
2.13.4

[PATCH 07/11] watchdog: ftwdt010: Delete surplus bindings

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:14

With the MOXA ART and Aspeed DT bindings covered by the
FTWDT010 binding, these surplus bindings can be deleted.

Signed-off-by: Linus Walleij <redacted>
---
 .../devicetree/bindings/watchdog/aspeed-wdt.txt          | 16 ----------------
 .../bindings/watchdog/moxa,moxart-watchdog.txt           | 15 ---------------
 2 files changed, 31 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
 delete mode 100644 Documentation/devicetree/bindings/watchdog/moxa,moxart-watchdog.txt
diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
deleted file mode 100644
index c5e74d7b4406..000000000000
--- a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-Aspeed Watchdog Timer
-
-Required properties:
- - compatible: must be one of:
-	- "aspeed,ast2400-wdt"
-	- "aspeed,ast2500-wdt"
-
- - reg: physical base address of the controller and length of memory mapped
-   region
-
-Example:
-
-	wdt1: watchdog at 1e785000 {
-		compatible = "aspeed,ast2400-wdt";
-		reg = <0x1e785000 0x1c>;
-	};
diff --git a/Documentation/devicetree/bindings/watchdog/moxa,moxart-watchdog.txt b/Documentation/devicetree/bindings/watchdog/moxa,moxart-watchdog.txt
deleted file mode 100644
index 1169857d1d12..000000000000
--- a/Documentation/devicetree/bindings/watchdog/moxa,moxart-watchdog.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-MOXA ART Watchdog timer
-
-Required properties:
-
-- compatible : Must be "moxa,moxart-watchdog"
-- reg : Should contain registers location and length
-- clocks : Should contain phandle for the clock that drives the counter
-
-Example:
-
-	watchdog: watchdog at 98500000 {
-		compatible = "moxa,moxart-watchdog";
-		reg = <0x98500000 0x10>;
-		clocks = <&coreclk>;
-	};
-- 
2.13.4

[PATCH 08/11] watchdog: ftwdt010/moxart: Merge MOXA ART into FTWDT010

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:15

These two drivers is for the same hardware, the only difference
is that Gemini uses the EXTCLK @5MHz by default (it also works
fine using PCLK) while the MOXA ART is using the PCLK to clock
the watchdog.

Delete the old MOXA ART driver and augment the FTWDT010 to
probe on this platform too, fetching the operating frequency
from the PCLK. Select the driver by default for ARCH_MOXART
to make a smooth transition of the platform.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig        |  11 +--
 drivers/watchdog/Makefile       |   1 -
 drivers/watchdog/ftwdt010_wdt.c |   1 +
 drivers/watchdog/moxart_wdt.c   | 178 ----------------------------------------
 4 files changed, 2 insertions(+), 189 deletions(-)
 delete mode 100644 drivers/watchdog/moxart_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fd44a542036a..beef6bb5c6d9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -326,6 +326,7 @@ config FTWDT010_WATCHDOG
 	depends on ARM || COMPILE_TEST
 	select WATCHDOG_CORE
 	default ARCH_GEMINI
+	default ARCH_MOXART
 	help
 	  Say Y here if to include support for the Faraday Technology
 	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
@@ -609,16 +610,6 @@ config RETU_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called retu_wdt.
 
-config MOXART_WDT
-	tristate "MOXART watchdog"
-	depends on ARCH_MOXART || COMPILE_TEST
-	help
-	  Say Y here to include Watchdog timer support for the watchdog
-	  existing on the MOXA ART SoC series platforms.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called moxart_wdt.
-
 config SIRFSOC_WATCHDOG
 	tristate "SiRFSOC watchdog"
 	depends on ARCH_SIRF || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index df91d7db821c..fcab71f0a1c7 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
 obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
 obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
 obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
-obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
 obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
 obj-$(CONFIG_ST_LPC_WATCHDOG) += st_lpc_wdt.o
 obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 7fc865eea28d..912b55e67110 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -298,6 +298,7 @@ static const struct dev_pm_ops ftwdt010_wdt_dev_pm_ops = {
 static const struct of_device_id ftwdt010_wdt_match[] = {
 	{ .compatible = "faraday,ftwdt010" },
 	{ .compatible = "cortina,gemini-watchdog" },
+	{ .compatible = "moxa,moxart-watchdog" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
diff --git a/drivers/watchdog/moxart_wdt.c b/drivers/watchdog/moxart_wdt.c
deleted file mode 100644
index 2c4a73d1e214..000000000000
--- a/drivers/watchdog/moxart_wdt.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * MOXA ART SoCs watchdog driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/watchdog.h>
-#include <linux/moduleparam.h>
-
-#define REG_COUNT			0x4
-#define REG_MODE			0x8
-#define REG_ENABLE			0xC
-
-struct moxart_wdt_dev {
-	struct watchdog_device dev;
-	void __iomem *base;
-	unsigned int clock_frequency;
-};
-
-static int heartbeat;
-
-static int moxart_wdt_restart(struct watchdog_device *wdt_dev,
-			      unsigned long action, void *data)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(1, moxart_wdt->base + REG_COUNT);
-	writel(0x5ab9, moxart_wdt->base + REG_MODE);
-	writel(0x03, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_stop(struct watchdog_device *wdt_dev)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(0, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_start(struct watchdog_device *wdt_dev)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(moxart_wdt->clock_frequency * wdt_dev->timeout,
-	       moxart_wdt->base + REG_COUNT);
-	writel(0x5ab9, moxart_wdt->base + REG_MODE);
-	writel(0x03, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_set_timeout(struct watchdog_device *wdt_dev,
-				  unsigned int timeout)
-{
-	wdt_dev->timeout = timeout;
-
-	return 0;
-}
-
-static const struct watchdog_info moxart_wdt_info = {
-	.identity       = "moxart-wdt",
-	.options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-			  WDIOF_MAGICCLOSE,
-};
-
-static const struct watchdog_ops moxart_wdt_ops = {
-	.owner          = THIS_MODULE,
-	.start          = moxart_wdt_start,
-	.stop           = moxart_wdt_stop,
-	.set_timeout    = moxart_wdt_set_timeout,
-	.restart        = moxart_wdt_restart,
-};
-
-static int moxart_wdt_probe(struct platform_device *pdev)
-{
-	struct moxart_wdt_dev *moxart_wdt;
-	struct device *dev = &pdev->dev;
-	struct device_node *node = dev->of_node;
-	struct resource *res;
-	struct clk *clk;
-	int err;
-	unsigned int max_timeout;
-	bool nowayout = WATCHDOG_NOWAYOUT;
-
-	moxart_wdt = devm_kzalloc(dev, sizeof(*moxart_wdt), GFP_KERNEL);
-	if (!moxart_wdt)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, moxart_wdt);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	moxart_wdt->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(moxart_wdt->base))
-		return PTR_ERR(moxart_wdt->base);
-
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("%s: of_clk_get failed\n", __func__);
-		return PTR_ERR(clk);
-	}
-
-	moxart_wdt->clock_frequency = clk_get_rate(clk);
-	if (moxart_wdt->clock_frequency == 0) {
-		pr_err("%s: incorrect clock frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	max_timeout = UINT_MAX / moxart_wdt->clock_frequency;
-
-	moxart_wdt->dev.info = &moxart_wdt_info;
-	moxart_wdt->dev.ops = &moxart_wdt_ops;
-	moxart_wdt->dev.timeout = max_timeout;
-	moxart_wdt->dev.min_timeout = 1;
-	moxart_wdt->dev.max_timeout = max_timeout;
-	moxart_wdt->dev.parent = dev;
-
-	watchdog_init_timeout(&moxart_wdt->dev, heartbeat, dev);
-	watchdog_set_nowayout(&moxart_wdt->dev, nowayout);
-	watchdog_set_restart_priority(&moxart_wdt->dev, 128);
-
-	watchdog_set_drvdata(&moxart_wdt->dev, moxart_wdt);
-
-	err = watchdog_register_device(&moxart_wdt->dev);
-	if (err)
-		return err;
-
-	dev_dbg(dev, "Watchdog enabled (heartbeat=%d sec, nowayout=%d)\n",
-		moxart_wdt->dev.timeout, nowayout);
-
-	return 0;
-}
-
-static int moxart_wdt_remove(struct platform_device *pdev)
-{
-	struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev);
-
-	moxart_wdt_stop(&moxart_wdt->dev);
-
-	return 0;
-}
-
-static const struct of_device_id moxart_watchdog_match[] = {
-	{ .compatible = "moxa,moxart-watchdog" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, moxart_watchdog_match);
-
-static struct platform_driver moxart_wdt_driver = {
-	.probe      = moxart_wdt_probe,
-	.remove     = moxart_wdt_remove,
-	.driver     = {
-		.name		= "moxart-watchdog",
-		.of_match_table	= moxart_watchdog_match,
-	},
-};
-module_platform_driver(moxart_wdt_driver);
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds");
-
-MODULE_DESCRIPTION("MOXART watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
-- 
2.13.4

[PATCH 09/11] watchdog: ftwdt010/aspeed: Merge Aspeed into FTWDT010

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:16

These two drivers is for the almost the same hardware,
the only differences are:
- The Aspeed IP block has been hacked to use a different
  magic value.
- The Aspeed has hard-wired 1MHz to the EXTCLK and
  apparently even disabled the use of PCLK for clocking
  the block on AST2500.

Delete the old Aspeed driver and augment the FTWDT010 to
probe on this platform too. Select the driver by default
for ARCH_ASPEED to make a smooth transition of the platform.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig        |  18 +---
 drivers/watchdog/Makefile       |   1 -
 drivers/watchdog/aspeed_wdt.c   | 200 ----------------------------------------
 drivers/watchdog/ftwdt010_wdt.c |  25 ++++-
 4 files changed, 25 insertions(+), 219 deletions(-)
 delete mode 100644 drivers/watchdog/aspeed_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index beef6bb5c6d9..0296fab14c35 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -327,10 +327,11 @@ config FTWDT010_WATCHDOG
 	select WATCHDOG_CORE
 	default ARCH_GEMINI
 	default ARCH_MOXART
+	default ARCH_ASPEED
 	help
 	  Say Y here if to include support for the Faraday Technology
-	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
-	  family of devices.
+	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini,
+	  MOXA ART and Aspeed families of devices.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ftwdt010_wdt.
@@ -733,19 +734,6 @@ config RENESAS_RZAWDT
 	  This driver adds watchdog support for the integrated watchdogs in the
 	  Renesas RZ/A SoCs. These watchdogs can be used to reset a system.
 
-config ASPEED_WATCHDOG
-	tristate "Aspeed 2400 watchdog support"
-	depends on ARCH_ASPEED || COMPILE_TEST
-	select WATCHDOG_CORE
-	help
-	  Say Y here to include support for the watchdog timer
-	  in Apseed BMC SoCs.
-
-	  This driver is required to reboot the SoC.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aspeed_wdt.
-
 config ZX2967_WATCHDOG
 	tristate "ZTE zx2967 SoCs watchdog support"
 	depends on ARCH_ZX
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index fcab71f0a1c7..a9701d39928d 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -82,7 +82,6 @@ obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
 obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
 obj-$(CONFIG_RENESAS_RZAWDT) += rza_wdt.o
-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
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
deleted file mode 100644
index 1c652582de40..000000000000
--- a/drivers/watchdog/aspeed_wdt.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2016 IBM Corporation
- *
- * Joel Stanley <joel@jms.id.au>
- *
- * 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 <linux/delay.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/watchdog.h>
-
-struct aspeed_wdt {
-	struct watchdog_device	wdd;
-	void __iomem		*base;
-	u32			ctrl;
-};
-
-static const struct of_device_id aspeed_wdt_of_table[] = {
-	{ .compatible = "aspeed,ast2400-wdt" },
-	{ .compatible = "aspeed,ast2500-wdt" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
-
-#define WDT_STATUS		0x00
-#define WDT_RELOAD_VALUE	0x04
-#define WDT_RESTART		0x08
-#define WDT_CTRL		0x0C
-#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
-#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
-#define   WDT_CTRL_1MHZ_CLK		BIT(4)
-#define   WDT_CTRL_WDT_EXT		BIT(3)
-#define   WDT_CTRL_WDT_INTR		BIT(2)
-#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
-#define   WDT_CTRL_ENABLE		BIT(0)
-
-#define WDT_RESTART_MAGIC	0x4755
-
-/* 32 bits@1MHz, in milliseconds */
-#define WDT_MAX_TIMEOUT_MS	4294967
-#define WDT_DEFAULT_TIMEOUT	30
-#define WDT_RATE_1MHZ		1000000
-
-static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
-{
-	return container_of(wdd, struct aspeed_wdt, wdd);
-}
-
-static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
-{
-	wdt->ctrl |= WDT_CTRL_ENABLE;
-
-	writel(0, wdt->base + WDT_CTRL);
-	writel(count, wdt->base + WDT_RELOAD_VALUE);
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-	writel(wdt->ctrl, wdt->base + WDT_CTRL);
-}
-
-static int aspeed_wdt_start(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ);
-
-	return 0;
-}
-
-static int aspeed_wdt_stop(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	wdt->ctrl &= ~WDT_CTRL_ENABLE;
-	writel(wdt->ctrl, wdt->base + WDT_CTRL);
-
-	return 0;
-}
-
-static int aspeed_wdt_ping(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-
-	return 0;
-}
-
-static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
-				  unsigned int timeout)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-	u32 actual;
-
-	wdd->timeout = timeout;
-
-	actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000);
-
-	writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE);
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-
-	return 0;
-}
-
-static int aspeed_wdt_restart(struct watchdog_device *wdd,
-			      unsigned long action, void *data)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000);
-
-	mdelay(1000);
-
-	return 0;
-}
-
-static const struct watchdog_ops aspeed_wdt_ops = {
-	.start		= aspeed_wdt_start,
-	.stop		= aspeed_wdt_stop,
-	.ping		= aspeed_wdt_ping,
-	.set_timeout	= aspeed_wdt_set_timeout,
-	.restart	= aspeed_wdt_restart,
-	.owner		= THIS_MODULE,
-};
-
-static const struct watchdog_info aspeed_wdt_info = {
-	.options	= WDIOF_KEEPALIVEPING
-			| WDIOF_MAGICCLOSE
-			| WDIOF_SETTIMEOUT,
-	.identity	= KBUILD_MODNAME,
-};
-
-static int aspeed_wdt_probe(struct platform_device *pdev)
-{
-	struct aspeed_wdt *wdt;
-	struct resource *res;
-	int ret;
-
-	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-	if (!wdt)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	wdt->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(wdt->base))
-		return PTR_ERR(wdt->base);
-
-	/*
-	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
-	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
-	 * good reason to have a faster watchdog counter.
-	 */
-	wdt->wdd.info = &aspeed_wdt_info;
-	wdt->wdd.ops = &aspeed_wdt_ops;
-	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
-	wdt->wdd.parent = &pdev->dev;
-
-	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
-	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
-
-	/*
-	 * Control reset on a per-device basis to ensure the
-	 * host is not affected by a BMC reboot, so only reset
-	 * the SOC and not the full chip
-	 */
-	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
-		WDT_CTRL_1MHZ_CLK |
-		WDT_CTRL_RESET_SYSTEM;
-
-	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
-		aspeed_wdt_start(&wdt->wdd);
-		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
-	}
-
-	ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct platform_driver aspeed_watchdog_driver = {
-	.probe = aspeed_wdt_probe,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
-	},
-};
-module_platform_driver(aspeed_watchdog_driver);
-
-MODULE_DESCRIPTION("Aspeed Watchdog Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 912b55e67110..072da594bcbd 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -7,6 +7,8 @@
  * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
  * Inspired by the MOXA ART driver from Jonas Jensen:
  * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
+ * Inspired by the Aspeed driver from Joel Stanley <joel@jms.id.au>:
+ * Copyright 2016 IBM Corporation
  *
  * 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
@@ -32,7 +34,9 @@
 #define FTWDT010_WDCR		0xC
 
 #define WDRESTART_MAGIC		0x5AB9
+#define ASPEED_MAGIC		0x4755
 
+#define ASPEED_RESET_FULL_CHIP	BIT(5)
 #define WDCR_EXTCLK		BIT(4)
 #define WDCR_WDEXT		BIT(3)
 #define WDCR_WDINTR		BIT(2)
@@ -48,6 +52,7 @@ struct ftwdt010_wdt {
 	struct clk		*extclk;
 	unsigned int		clk_freq;
 	bool			use_extclk;
+	u32			magic;
 };
 
 static inline
@@ -63,7 +68,7 @@ static int ftwdt010_wdt_restart(struct watchdog_device *wdd,
 	u32 enable;
 
 	writel(1, gwdt->base + FTWDT010_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 	enable = WDCR_SYS_RST | WDCR_ENABLE;
 	if (gwdt->use_extclk)
 		enable |= WDCR_EXTCLK;
@@ -78,7 +83,7 @@ static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 	u32 enable;
 
 	writel(wdd->timeout * gwdt->clk_freq, gwdt->base + FTWDT010_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
 	enable = WDCR_SYS_RST;
 	if (gwdt->use_extclk)
@@ -105,7 +110,7 @@ static int ftwdt010_wdt_ping(struct watchdog_device *wdd)
 {
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 
 	return 0;
 }
@@ -153,6 +158,7 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
+	bool is_aspeed;
 	int irq;
 	int ret;
 
@@ -167,6 +173,10 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 
 	gwdt->use_extclk = of_property_read_bool(np, "faraday,use-extclk");
 
+	/* We want to know if we are aspeed */
+	is_aspeed = of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
+		of_device_is_compatible(np, "aspeed,ast2500-wdt");
+
 	gwdt->pclk = devm_clk_get(dev, "PCLK");
 	if (!IS_ERR(gwdt->pclk)) {
 		ret = clk_prepare_enable(gwdt->pclk);
@@ -198,6 +208,11 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 			gwdt->use_extclk = true;
 			dev_info(dev, "assume 5MHz EXTCLK on Gemini\n");
 		}
+		if (is_aspeed) {
+			gwdt->clk_freq = 1000000;
+			gwdt->use_extclk = true;
+			dev_info(dev, "assume 1MHz EXTCLK on Aspeed\n");
+		}
 	}
 
 	if (gwdt->clk_freq == 0) {
@@ -211,6 +226,10 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	gwdt->wdd.min_timeout = 1;
 	gwdt->wdd.max_timeout = UINT_MAX / gwdt->clk_freq;
 	gwdt->wdd.parent = dev;
+	if (is_aspeed)
+		gwdt->magic = ASPEED_MAGIC;
+	else
+		gwdt->magic = WDRESTART_MAGIC;
 
 	/*
 	 * If 'timeout-sec' unspecified in devicetree, assume a 13 second
-- 
2.13.4

[PATCH 10/11] ARM: dts: fix PCLK name on Gemini and MOXA ART

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:17

These platforms provide a clock to their watchdog, in each
case this is the peripheral clock (PCLK), so explicitly
name the clock in the device tree.

Take this opportunity to add the "faraday,ftwdt010"
compatible as fallback to the watchdog IP blocks.

Signed-off-by: Linus Walleij <redacted>
---
 arch/arm/boot/dts/gemini.dtsi | 3 ++-
 arch/arm/boot/dts/moxart.dtsi | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/gemini.dtsi b/arch/arm/boot/dts/gemini.dtsi
index c68e8d430234..f0d178c77153 100644
--- a/arch/arm/boot/dts/gemini.dtsi
+++ b/arch/arm/boot/dts/gemini.dtsi
@@ -145,11 +145,12 @@
 		};
 
 		watchdog at 41000000 {
-			compatible = "cortina,gemini-watchdog";
+			compatible = "cortina,gemini-watchdog", "faraday,ftwdt010";
 			reg = <0x41000000 0x1000>;
 			interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
 			resets = <&syscon GEMINI_RESET_WDOG>;
 			clocks = <&syscon GEMINI_CLK_APB>;
+			clock-names = "PCLK";
 		};
 
 		uart0: serial at 42000000 {
diff --git a/arch/arm/boot/dts/moxart.dtsi b/arch/arm/boot/dts/moxart.dtsi
index 1f4c795d3f72..da7b3237bfe9 100644
--- a/arch/arm/boot/dts/moxart.dtsi
+++ b/arch/arm/boot/dts/moxart.dtsi
@@ -87,9 +87,10 @@
 		};
 
 		watchdog: watchdog at 98500000 {
-			compatible = "moxa,moxart-watchdog";
+			compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
 			reg = <0x98500000 0x10>;
 			clocks = <&clk_apb>;
+			clock-names = "PCLK";
 		};
 
 		sdhci: sdhci at 98e00000 {
-- 
2.13.4

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Linus Walleij <hidden>
Date: 2017-08-12 18:43:18

This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired so to obtain the frequency from it, it needs to
be present in the device tree, and for completeness the
PCLK should also be referenced and enabled anyways.

Take this opportunity to add the "faraday,ftwdt010"
compatible as fallback to the watchdog IP blocks.

Signed-off-by: Linus Walleij <redacted>
---
 arch/arm/boot/dts/aspeed-g4.dtsi |  7 +++++--
 arch/arm/boot/dts/aspeed-g5.dtsi | 12 +++++++++---
 2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index 8a04c7e2d818..23b100383c15 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -895,16 +895,19 @@
 			};
 
 			wdt1: wdt at 1e785000 {
-				compatible = "aspeed,ast2400-wdt";
+				compatible = "aspeed,ast2400-wdt", "faraday,ftwdt010";
 				reg = <0x1e785000 0x1c>;
 				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
 			};
 
 			wdt2: wdt at 1e785020 {
-				compatible = "aspeed,ast2400-wdt";
+				compatible = "aspeed,ast2400-wdt", "faraday,ftwdt010";
 				reg = <0x1e785020 0x1c>;
 				interrupts = <27>;
 				clocks = <&clk_apb>;
+				clock-names = "PCLK";
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 9cffe347b828..2322d72cd8a9 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -1003,21 +1003,27 @@
 
 
 			wdt1: wdt at 1e785000 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
 				reg = <0x1e785000 0x20>;
 				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
 			};
 
 			wdt2: wdt at 1e785020 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
 				reg = <0x1e785020 0x20>;
 				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
 				status = "disabled";
 			};
 
 			wdt3: wdt at 1e785040 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
 				reg = <0x1e785040 0x20>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
 				status = "disabled";
 			};
 
-- 
2.13.4

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: joel@jms.id.au (Joel Stanley)
Date: 2017-08-14 01:24:41

Hi Linus,

On Sun, Aug 13, 2017 at 4:13 AM, Linus Walleij [off-list ref] wrote:
The MOXA ART and Aspeed watchdogs are clearly based on the
Faraday Technology FTWDT010 IP block.
They have a similar register interface, but I'm told they are not the same IP.

We've got some patches on the list that add some extra registers to
the driver for the ast2500. If we decide to merge the drivers, that
support will need to be included.

Andrew was working on that, I'll let him follow up on the details.
This series consolidates the drivers into one by extending
the Gemini driver to be as generic as possible, renaming it
to ftwdt010_wdt and merging the two other drivers into it.

As similar approach was used for the FTTMR010 driver in the
past.

The series ends with two patches that will be applied to
the ARM SoC tree to fix up the PCLK annotations, but these
are not needed to make the consolidation, patches 1-9 can
be applied directly to the watchdog tree to perform the
consolidation.
The clock isn't called PCLK in the Aspeed documentation (similarly for
the timer, but I was too slow to speak up in that case).

I'm trying to find some time to write a proper clock driver so it's
clear how the clocks are set out in the Aspeed.

Cheers,

Joel

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: Andrew Jeffery <hidden>
Date: 2017-08-14 03:08:16

On Mon, 2017-08-14 at 10:54 +0930, Joel Stanley wrote:
Hi Linus,
?
On Sun, Aug 13, 2017 at 4:13 AM, Linus Walleij [off-list ref] wrote:
quoted
The MOXA ART and Aspeed watchdogs are clearly based on the
Faraday Technology FTWDT010 IP block.
?
They have a similar register interface, but I'm told they are not the same IP.
?
We've got some patches on the list that add some extra registers to
the driver for the ast2500. If we decide to merge the drivers, that
support will need to be included.
?
Andrew was working on that, I'll let him follow up on the details.
There are two series on the lists expanding driver support for the Aspeed
watchdog, one from Chris Bostic and another from myself:

1. [PATCH v5 0/2] Add ASPEED watchdog device tree properties:

	https://lkml.org/lkml/2017/7/17/777?

2. [PATCH 0/2] watchdog: aspeed: External reset signal properties:

	https://www.spinics.net/lists/kernel/msg2570666.html?

I don't have the datasheets for either the Moxa or Faraday SoCs, so I can't
assess how the support I've added for the external pulse properties on Aspeed
hardware impacts/is impacted by the merge. Chris' changes on the otherhand look
like they could be generalised. At least, the vendor prefix on the devicetree
properties he defined could perhaps be changed from aspeed to faraday.

Cheers,

Andrew

PS: Patch 10/11 failed to apply for me against several trees, failing on the
hunk for arch/arm/boot/dts/gemini.dtsi. Is there an unmentioned dependency?
?
quoted
This series consolidates the drivers into one by extending
the Gemini driver to be as generic as possible, renaming it
to ftwdt010_wdt and merging the two other drivers into it.
?
As similar approach was used for the FTTMR010 driver in the
past.
?
The series ends with two patches that will be applied to
the ARM SoC tree to fix up the PCLK annotations, but these
are not needed to make the consolidation, patches 1-9 can
be applied directly to the watchdog tree to perform the
consolidation.
?
The clock isn't called PCLK in the Aspeed documentation (similarly for
the timer, but I was too slow to speak up in that case).
?
I'm trying to find some time to write a proper clock driver so it's
clear how the clocks are set out in the Aspeed.
?
Cheers,
?
Joel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170814/5e4c82bd/attachment.sig>

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: Linus Walleij <hidden>
Date: 2017-08-14 12:31:35

On Mon, Aug 14, 2017 at 3:24 AM, Joel Stanley [off-list ref] wrote:
On Sun, Aug 13, 2017 at 4:13 AM, Linus Walleij [off-list ref] wrote:
quoted
The MOXA ART and Aspeed watchdogs are clearly based on the
Faraday Technology FTWDT010 IP block.
They have a similar register interface, but I'm told they are not the same IP.
They are too similar to not be related somehow.

I guess it is one of those Shanzhai-mindset things where IP VHDL
or Verilog code is being copied around at silicon foundries in Asia
and turn up in different chips "independently" of each other.

It doesn't really matter if they "are" the same (as in: silicon vendor
admits that they are), if it walks like a duck, act and talks like a duck,
it is a duck. And we use the same driver.
We've got some patches on the list that add some extra registers to
the driver for the ast2500. If we decide to merge the drivers, that
support will need to be included.
Hm I was not aware, need to read up on it.
Andrew was working on that, I'll let him follow up on the details.

The clock isn't called PCLK in the Aspeed documentation (similarly for
the timer, but I was too slow to speak up in that case).
"PCLK" is just short for "peripheral block", just like other such
shorthands like "APB" (AMBA peripheral bridge clock). It's
a generic term.

Preferrably it should use the name from the IP vendor, but when in
conflict about names, it's too much trouble to use different names
IMO so I think "PCLK" is just fine.

Yours,
Linus Walleij

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: Linus Walleij <hidden>
Date: 2017-08-14 12:36:35

On Mon, Aug 14, 2017 at 5:08 AM, Andrew Jeffery [off-list ref] wrote:
There are two series on the lists expanding driver support for the Aspeed
watchdog, one from Chris Bostic and another from myself:

1. [PATCH v5 0/2] Add ASPEED watchdog device tree properties:

        https://lkml.org/lkml/2017/7/17/777
Looks all right. The SoC vs whole chip reset signal big is an
Aspeed-specific extension AFAICT.
2. [PATCH 0/2] watchdog: aspeed: External reset signal properties:

        https://www.spinics.net/lists/kernel/msg2570666.html
The external reset exists also in the Faraday FTWDT010 block, in the
same bit. (No coincidence...) but neither the Gemini or the MOXA ART
is using it as far as I know.
I don't have the datasheets for either the Moxa or Faraday SoCs, so I can't
assess how the support I've added for the external pulse properties on Aspeed
hardware impacts/is impacted by the merge.
It's no big deal, I can rewrite the patches in the end of the series on top
of that stuff also adding this functionality.
Chris' changes on the otherhand look
like they could be generalised. At least, the vendor prefix on the devicetree
properties he defined could perhaps be changed from aspeed to faraday.
The "aspeed,reset-type" is fine since it is Aspeed-only.

External reset is part of the Faraday IP block so it should be
"faraday,external-reset-signal" or so.

I will try to see if I can find the patches and comment directly.

Yours,
Linus Walleij

[PATCH 00/11] watchdog: Consolidate FTWDT010 derivatives

From: Linus Walleij <hidden>
Date: 2017-08-14 12:39:48

On Sat, Aug 12, 2017 at 8:43 PM, Linus Walleij [off-list ref] wrote:
The MOXA ART and Aspeed watchdogs are clearly based on the
Faraday Technology FTWDT010 IP block.
Wim/Guenther: it is perfectly fine to just stop merging the series after
the say top 3 or top 4 ones etc. The do not need to be applied on an
all-or-nothing basis.

Yours,
Linus Walleij

[PATCH 02/11] watchdog: gemini/ftwdt010: rename driver and symbols

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-14 15:01:05

On Sat, Aug 12, 2017 at 08:43:09PM +0200, Linus Walleij wrote:
quoted hunk
This renames all the driver files and symbols for the Gemini
watchdog to FTWDT010 as it has been revealed that this IP block
is a generic watchdog timer from Faraday Technology used in
several SoC designs.

Select thid driver by default for the Gemini, it is a sensible
driver to always have enabled.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig                          |  14 +--
 drivers/watchdog/Makefile                         |   2 +-
 drivers/watchdog/{gemini_wdt.c => ftwdt010_wdt.c} | 117 +++++++++++-----------
 3 files changed, 68 insertions(+), 65 deletions(-)
 rename drivers/watchdog/{gemini_wdt.c => ftwdt010_wdt.c} (50%)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c722cbfdc7e6..fd44a542036a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -321,16 +321,18 @@ config 977_WATCHDOG
 
 	  Not sure? It's safe to say N.
 
-config GEMINI_WATCHDOG
-	tristate "Gemini watchdog"
-	depends on ARCH_GEMINI
+config FTWDT010_WATCHDOG
+	tristate "Faraday Technology FTWDT010 watchdog"
+	depends on ARM || COMPILE_TEST
Did you test this ? I am kind of wary about COMPILE_TEST in watchdog drivers.
I tried to enable that a while ago, and we had to spend a couple of releases
fixing the fallout (even though I had tried to make sure that everything
builds).
quoted hunk
 	select WATCHDOG_CORE
+	default ARCH_GEMINI
 	help
-	  Say Y here if to include support for the watchdog timer
-	  embedded in the Cortina Systems Gemini family of devices.
+	  Say Y here if to include support for the Faraday Technology
+	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
+	  family of devices.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called gemini_wdt.
+	  module will be called ftwdt010_wdt.
 
 config IXP4XX_WATCHDOG
 	tristate "IXP4xx Watchdog"
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 56adf9fa67d0..df91d7db821c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_GEMINI_WATCHDOG) += gemini_wdt.o
+obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
diff --git a/drivers/watchdog/gemini_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
similarity index 50%
rename from drivers/watchdog/gemini_wdt.c
rename to drivers/watchdog/ftwdt010_wdt.c
index 8155aa619e4c..637ffd812f0b 100644
--- a/drivers/watchdog/gemini_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -1,5 +1,5 @@
 /*
- * Watchdog driver for Cortina Systems Gemini SoC
+ * Watchdog driver for Faraday Technology FTWDT010
  *
  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  *
@@ -22,10 +22,10 @@
 #include <linux/slab.h>
 #include <linux/watchdog.h>
 
-#define GEMINI_WDCOUNTER	0x0
-#define GEMINI_WDLOAD		0x4
-#define GEMINI_WDRESTART	0x8
-#define GEMINI_WDCR		0xC
+#define FTWDT010_WDCOUNTER	0x0
+#define FTWDT010_WDLOAD		0x4
+#define FTWDT010_WDRESTART	0x8
+#define FTWDT010_WDCR		0xC
 
 #define WDRESTART_MAGIC		0x5AB9
 
@@ -35,79 +35,79 @@
 
 #define WDT_CLOCK		5000000		/* 5 MHz */
 
-struct gemini_wdt {
+struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
 };
 
 static inline
-struct gemini_wdt *to_gemini_wdt(struct watchdog_device *wdd)
+struct ftwdt010_wdt *to_ftwdt010_wdt(struct watchdog_device *wdd)
 {
-	return container_of(wdd, struct gemini_wdt, wdd);
+	return container_of(wdd, struct ftwdt010_wdt, wdd);
 }
 
-static int gemini_wdt_start(struct watchdog_device *wdd)
+static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(wdd->timeout * WDT_CLOCK, gwdt->base + GEMINI_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + GEMINI_WDRESTART);
+	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
+	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
 	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
-			gwdt->base + GEMINI_WDCR);
+			gwdt->base + FTWDT010_WDCR);
 	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
-			gwdt->base + GEMINI_WDCR);
+			gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int gemini_wdt_stop(struct watchdog_device *wdd)
+static int ftwdt010_wdt_stop(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(0, gwdt->base + GEMINI_WDCR);
+	writel(0, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int gemini_wdt_ping(struct watchdog_device *wdd)
+static int ftwdt010_wdt_ping(struct watchdog_device *wdd)
 {
-	struct gemini_wdt *gwdt = to_gemini_wdt(wdd);
+	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(WDRESTART_MAGIC, gwdt->base + GEMINI_WDRESTART);
+	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 
 	return 0;
 }
 
-static int gemini_wdt_set_timeout(struct watchdog_device *wdd,
+static int ftwdt010_wdt_set_timeout(struct watchdog_device *wdd,
 				  unsigned int timeout)
 {
 	wdd->timeout = timeout;
 	if (watchdog_active(wdd))
-		gemini_wdt_start(wdd);
+		ftwdt010_wdt_start(wdd);
 
 	return 0;
 }
 
-static irqreturn_t gemini_wdt_interrupt(int irq, void *data)
+static irqreturn_t ftwdt010_wdt_interrupt(int irq, void *data)
 {
-	struct gemini_wdt *gwdt = data;
+	struct ftwdt010_wdt *gwdt = data;
 
 	watchdog_notify_pretimeout(&gwdt->wdd);
 
 	return IRQ_HANDLED;
 }
 
-static const struct watchdog_ops gemini_wdt_ops = {
-	.start		= gemini_wdt_start,
-	.stop		= gemini_wdt_stop,
-	.ping		= gemini_wdt_ping,
-	.set_timeout	= gemini_wdt_set_timeout,
+static const struct watchdog_ops ftwdt010_wdt_ops = {
+	.start		= ftwdt010_wdt_start,
+	.stop		= ftwdt010_wdt_stop,
+	.ping		= ftwdt010_wdt_ping,
+	.set_timeout	= ftwdt010_wdt_set_timeout,
 	.owner		= THIS_MODULE,
 };
 
-static const struct watchdog_info gemini_wdt_info = {
+static const struct watchdog_info ftwdt010_wdt_info = {
 	.options	= WDIOF_KEEPALIVEPING
 			| WDIOF_MAGICCLOSE
 			| WDIOF_SETTIMEOUT,
@@ -115,11 +115,11 @@ static const struct watchdog_info gemini_wdt_info = {
 };
 
 
-static int gemini_wdt_probe(struct platform_device *pdev)
+static int ftwdt010_wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
-	struct gemini_wdt *gwdt;
+	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
 	int irq;
 	int ret;
@@ -138,8 +138,8 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	gwdt->dev = dev;
-	gwdt->wdd.info = &gemini_wdt_info;
-	gwdt->wdd.ops = &gemini_wdt_ops;
+	gwdt->wdd.info = &ftwdt010_wdt_info;
+	gwdt->wdd.ops = &ftwdt010_wdt_ops;
 	gwdt->wdd.min_timeout = 1;
 	gwdt->wdd.max_timeout = 0xFFFFFFFF / WDT_CLOCK;
 	gwdt->wdd.parent = dev;
@@ -151,14 +151,14 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 	gwdt->wdd.timeout = 13U;
 	watchdog_init_timeout(&gwdt->wdd, 0, dev);
 
-	reg = readw(gwdt->base + GEMINI_WDCR);
+	reg = readw(gwdt->base + FTWDT010_WDCR);
 	if (reg & WDCR_ENABLE) {
 		/* Watchdog was enabled by the bootloader, disable it. */
 		reg &= ~WDCR_ENABLE;
-		writel(reg, gwdt->base + GEMINI_WDCR);
+		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
-	ret = devm_request_irq(dev, irq, gemini_wdt_interrupt, 0,
+	ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
 			       "watchdog bark", gwdt);
 	if (ret)
 		return ret;
@@ -171,59 +171,60 @@ static int gemini_wdt_probe(struct platform_device *pdev)
 
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, gwdt);
-	dev_info(dev, "Gemini watchdog driver enabled\n");
+	dev_info(dev, "FTWDT010 watchdog driver enabled\n");
 
 	return 0;
 }
 
-static int __maybe_unused gemini_wdt_suspend(struct device *dev)
+static int __maybe_unused ftwdt010_wdt_suspend(struct device *dev)
 {
-	struct gemini_wdt *gwdt = dev_get_drvdata(dev);
+	struct ftwdt010_wdt *gwdt = dev_get_drvdata(dev);
 	unsigned int reg;
 
-	reg = readw(gwdt->base + GEMINI_WDCR);
+	reg = readw(gwdt->base + FTWDT010_WDCR);
 	reg &= ~WDCR_ENABLE;
-	writel(reg, gwdt->base + GEMINI_WDCR);
+	writel(reg, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
 
-static int __maybe_unused gemini_wdt_resume(struct device *dev)
+static int __maybe_unused ftwdt010_wdt_resume(struct device *dev)
 {
-	struct gemini_wdt *gwdt = dev_get_drvdata(dev);
+	struct ftwdt010_wdt *gwdt = dev_get_drvdata(dev);
 	unsigned int reg;
 
 	if (watchdog_active(&gwdt->wdd)) {
-		reg = readw(gwdt->base + GEMINI_WDCR);
+		reg = readw(gwdt->base + FTWDT010_WDCR);
 		reg |= WDCR_ENABLE;
-		writel(reg, gwdt->base + GEMINI_WDCR);
+		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
 	return 0;
 }
 
-static const struct dev_pm_ops gemini_wdt_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(gemini_wdt_suspend,
-				gemini_wdt_resume)
+static const struct dev_pm_ops ftwdt010_wdt_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ftwdt010_wdt_suspend,
+				ftwdt010_wdt_resume)
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id gemini_wdt_match[] = {
+static const struct of_device_id ftwdt010_wdt_match[] = {
+	{ .compatible = "faraday,ftwdt010" },
 	{ .compatible = "cortina,gemini-watchdog" },
 	{},
 };
-MODULE_DEVICE_TABLE(of, gemini_wdt_match);
+MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
 #endif
 
-static struct platform_driver gemini_wdt_driver = {
-	.probe		= gemini_wdt_probe,
+static struct platform_driver ftwdt010_wdt_driver = {
+	.probe		= ftwdt010_wdt_probe,
 	.driver		= {
-		.name	= "gemini-wdt",
-		.of_match_table = of_match_ptr(gemini_wdt_match),
-		.pm = &gemini_wdt_dev_pm_ops,
+		.name	= "ftwdt010-wdt",
+		.of_match_table = of_match_ptr(ftwdt010_wdt_match),
+		.pm = &ftwdt010_wdt_dev_pm_ops,
 	},
 };
-module_platform_driver(gemini_wdt_driver);
+module_platform_driver(ftwdt010_wdt_driver);
 MODULE_AUTHOR("Linus Walleij");
-MODULE_DESCRIPTION("Watchdog driver for Gemini");
+MODULE_DESCRIPTION("Watchdog driver for Faraday Technology FTWDT010");
 MODULE_LICENSE("GPL");
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 09/11] watchdog: ftwdt010/aspeed: Merge Aspeed into FTWDT010

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-14 15:04:34

On Sat, Aug 12, 2017 at 08:43:16PM +0200, Linus Walleij wrote:
These two drivers is for the almost the same hardware,
the only differences are:
- The Aspeed IP block has been hacked to use a different
  magic value.
- The Aspeed has hard-wired 1MHz to the EXTCLK and
  apparently even disabled the use of PCLK for clocking
  the block on AST2500.
Confused. I thought the ast2500 is an EC. Am I missing something ?

Guenter
quoted hunk
Delete the old Aspeed driver and augment the FTWDT010 to
probe on this platform too. Select the driver by default
for ARCH_ASPEED to make a smooth transition of the platform.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig        |  18 +---
 drivers/watchdog/Makefile       |   1 -
 drivers/watchdog/aspeed_wdt.c   | 200 ----------------------------------------
 drivers/watchdog/ftwdt010_wdt.c |  25 ++++-
 4 files changed, 25 insertions(+), 219 deletions(-)
 delete mode 100644 drivers/watchdog/aspeed_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index beef6bb5c6d9..0296fab14c35 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -327,10 +327,11 @@ config FTWDT010_WATCHDOG
 	select WATCHDOG_CORE
 	default ARCH_GEMINI
 	default ARCH_MOXART
+	default ARCH_ASPEED
 	help
 	  Say Y here if to include support for the Faraday Technology
-	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
-	  family of devices.
+	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini,
+	  MOXA ART and Aspeed families of devices.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ftwdt010_wdt.
@@ -733,19 +734,6 @@ config RENESAS_RZAWDT
 	  This driver adds watchdog support for the integrated watchdogs in the
 	  Renesas RZ/A SoCs. These watchdogs can be used to reset a system.
 
-config ASPEED_WATCHDOG
-	tristate "Aspeed 2400 watchdog support"
-	depends on ARCH_ASPEED || COMPILE_TEST
-	select WATCHDOG_CORE
-	help
-	  Say Y here to include support for the watchdog timer
-	  in Apseed BMC SoCs.
-
-	  This driver is required to reboot the SoC.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aspeed_wdt.
-
 config ZX2967_WATCHDOG
 	tristate "ZTE zx2967 SoCs watchdog support"
 	depends on ARCH_ZX
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index fcab71f0a1c7..a9701d39928d 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -82,7 +82,6 @@ obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
 obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
 obj-$(CONFIG_RENESAS_RZAWDT) += rza_wdt.o
-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
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
deleted file mode 100644
index 1c652582de40..000000000000
--- a/drivers/watchdog/aspeed_wdt.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2016 IBM Corporation
- *
- * Joel Stanley <joel@jms.id.au>
- *
- * 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 <linux/delay.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/watchdog.h>
-
-struct aspeed_wdt {
-	struct watchdog_device	wdd;
-	void __iomem		*base;
-	u32			ctrl;
-};
-
-static const struct of_device_id aspeed_wdt_of_table[] = {
-	{ .compatible = "aspeed,ast2400-wdt" },
-	{ .compatible = "aspeed,ast2500-wdt" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
-
-#define WDT_STATUS		0x00
-#define WDT_RELOAD_VALUE	0x04
-#define WDT_RESTART		0x08
-#define WDT_CTRL		0x0C
-#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
-#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
-#define   WDT_CTRL_1MHZ_CLK		BIT(4)
-#define   WDT_CTRL_WDT_EXT		BIT(3)
-#define   WDT_CTRL_WDT_INTR		BIT(2)
-#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
-#define   WDT_CTRL_ENABLE		BIT(0)
-
-#define WDT_RESTART_MAGIC	0x4755
-
-/* 32 bits at 1MHz, in milliseconds */
-#define WDT_MAX_TIMEOUT_MS	4294967
-#define WDT_DEFAULT_TIMEOUT	30
-#define WDT_RATE_1MHZ		1000000
-
-static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
-{
-	return container_of(wdd, struct aspeed_wdt, wdd);
-}
-
-static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
-{
-	wdt->ctrl |= WDT_CTRL_ENABLE;
-
-	writel(0, wdt->base + WDT_CTRL);
-	writel(count, wdt->base + WDT_RELOAD_VALUE);
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-	writel(wdt->ctrl, wdt->base + WDT_CTRL);
-}
-
-static int aspeed_wdt_start(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ);
-
-	return 0;
-}
-
-static int aspeed_wdt_stop(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	wdt->ctrl &= ~WDT_CTRL_ENABLE;
-	writel(wdt->ctrl, wdt->base + WDT_CTRL);
-
-	return 0;
-}
-
-static int aspeed_wdt_ping(struct watchdog_device *wdd)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-
-	return 0;
-}
-
-static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
-				  unsigned int timeout)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-	u32 actual;
-
-	wdd->timeout = timeout;
-
-	actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000);
-
-	writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE);
-	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
-
-	return 0;
-}
-
-static int aspeed_wdt_restart(struct watchdog_device *wdd,
-			      unsigned long action, void *data)
-{
-	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
-
-	aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000);
-
-	mdelay(1000);
-
-	return 0;
-}
-
-static const struct watchdog_ops aspeed_wdt_ops = {
-	.start		= aspeed_wdt_start,
-	.stop		= aspeed_wdt_stop,
-	.ping		= aspeed_wdt_ping,
-	.set_timeout	= aspeed_wdt_set_timeout,
-	.restart	= aspeed_wdt_restart,
-	.owner		= THIS_MODULE,
-};
-
-static const struct watchdog_info aspeed_wdt_info = {
-	.options	= WDIOF_KEEPALIVEPING
-			| WDIOF_MAGICCLOSE
-			| WDIOF_SETTIMEOUT,
-	.identity	= KBUILD_MODNAME,
-};
-
-static int aspeed_wdt_probe(struct platform_device *pdev)
-{
-	struct aspeed_wdt *wdt;
-	struct resource *res;
-	int ret;
-
-	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-	if (!wdt)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	wdt->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(wdt->base))
-		return PTR_ERR(wdt->base);
-
-	/*
-	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
-	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
-	 * good reason to have a faster watchdog counter.
-	 */
-	wdt->wdd.info = &aspeed_wdt_info;
-	wdt->wdd.ops = &aspeed_wdt_ops;
-	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
-	wdt->wdd.parent = &pdev->dev;
-
-	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
-	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
-
-	/*
-	 * Control reset on a per-device basis to ensure the
-	 * host is not affected by a BMC reboot, so only reset
-	 * the SOC and not the full chip
-	 */
-	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
-		WDT_CTRL_1MHZ_CLK |
-		WDT_CTRL_RESET_SYSTEM;
-
-	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
-		aspeed_wdt_start(&wdt->wdd);
-		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
-	}
-
-	ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct platform_driver aspeed_watchdog_driver = {
-	.probe = aspeed_wdt_probe,
-	.driver = {
-		.name = KBUILD_MODNAME,
-		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
-	},
-};
-module_platform_driver(aspeed_watchdog_driver);
-
-MODULE_DESCRIPTION("Aspeed Watchdog Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 912b55e67110..072da594bcbd 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -7,6 +7,8 @@
  * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
  * Inspired by the MOXA ART driver from Jonas Jensen:
  * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
+ * Inspired by the Aspeed driver from Joel Stanley <joel@jms.id.au>:
+ * Copyright 2016 IBM Corporation
  *
  * 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
@@ -32,7 +34,9 @@
 #define FTWDT010_WDCR		0xC
 
 #define WDRESTART_MAGIC		0x5AB9
+#define ASPEED_MAGIC		0x4755
 
+#define ASPEED_RESET_FULL_CHIP	BIT(5)
 #define WDCR_EXTCLK		BIT(4)
 #define WDCR_WDEXT		BIT(3)
 #define WDCR_WDINTR		BIT(2)
@@ -48,6 +52,7 @@ struct ftwdt010_wdt {
 	struct clk		*extclk;
 	unsigned int		clk_freq;
 	bool			use_extclk;
+	u32			magic;
 };
 
 static inline
@@ -63,7 +68,7 @@ static int ftwdt010_wdt_restart(struct watchdog_device *wdd,
 	u32 enable;
 
 	writel(1, gwdt->base + FTWDT010_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 	enable = WDCR_SYS_RST | WDCR_ENABLE;
 	if (gwdt->use_extclk)
 		enable |= WDCR_EXTCLK;
@@ -78,7 +83,7 @@ static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 	u32 enable;
 
 	writel(wdd->timeout * gwdt->clk_freq, gwdt->base + FTWDT010_WDLOAD);
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
 	enable = WDCR_SYS_RST;
 	if (gwdt->use_extclk)
@@ -105,7 +110,7 @@ static int ftwdt010_wdt_ping(struct watchdog_device *wdd)
 {
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 
-	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
+	writel(gwdt->magic, gwdt->base + FTWDT010_WDRESTART);
 
 	return 0;
 }
@@ -153,6 +158,7 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
+	bool is_aspeed;
 	int irq;
 	int ret;
 
@@ -167,6 +173,10 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 
 	gwdt->use_extclk = of_property_read_bool(np, "faraday,use-extclk");
 
+	/* We want to know if we are aspeed */
+	is_aspeed = of_device_is_compatible(np, "aspeed,ast2400-wdt") ||
+		of_device_is_compatible(np, "aspeed,ast2500-wdt");
+
 	gwdt->pclk = devm_clk_get(dev, "PCLK");
 	if (!IS_ERR(gwdt->pclk)) {
 		ret = clk_prepare_enable(gwdt->pclk);
@@ -198,6 +208,11 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 			gwdt->use_extclk = true;
 			dev_info(dev, "assume 5MHz EXTCLK on Gemini\n");
 		}
+		if (is_aspeed) {
+			gwdt->clk_freq = 1000000;
+			gwdt->use_extclk = true;
+			dev_info(dev, "assume 1MHz EXTCLK on Aspeed\n");
+		}
 	}
 
 	if (gwdt->clk_freq == 0) {
@@ -211,6 +226,10 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	gwdt->wdd.min_timeout = 1;
 	gwdt->wdd.max_timeout = UINT_MAX / gwdt->clk_freq;
 	gwdt->wdd.parent = dev;
+	if (is_aspeed)
+		gwdt->magic = ASPEED_MAGIC;
+	else
+		gwdt->magic = WDRESTART_MAGIC;
 
 	/*
 	 * If 'timeout-sec' unspecified in devicetree, assume a 13 second
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 03/11] watchdog: ftwdt010: Make interrupt optional

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-14 15:09:20

On Sat, Aug 12, 2017 at 08:43:10PM +0200, Linus Walleij wrote:
quoted hunk
The Moxart does not appear to be using the interrupt from the
watchdog timer, maybe it's not even routed, so as to support
more architectures with this driver, make the interrupt
optional.

While we are at it: actually enable the use of the interrupt
if present by setting the right bit in the control register
and define the missing control register bits.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/ftwdt010_wdt.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 637ffd812f0b..ab38a3a89300 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -30,6 +30,8 @@
 #define WDRESTART_MAGIC		0x5AB9
 
 #define WDCR_CLOCK_5MHZ		BIT(4)
+#define WDCR_WDEXT		BIT(3)
+#define WDCR_WDINTR		BIT(2)
 #define WDCR_SYS_RST		BIT(1)
 #define WDCR_ENABLE		BIT(0)
 
@@ -39,6 +41,7 @@ struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
+	bool			has_irq;
 };
 
 static inline
@@ -50,14 +53,18 @@ struct ftwdt010_wdt *to_ftwdt010_wdt(struct watchdog_device *wdd)
 static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 {
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
+	u32 enable;
 
 	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
 	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
-	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
-			gwdt->base + FTWDT010_WDCR);
-	writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
-			gwdt->base + FTWDT010_WDCR);
+	enable = WDCR_CLOCK_5MHZ | WDCR_SYS_RST;
+	writel(enable, gwdt->base + FTWDT010_WDCR);
+	enable |= WDCR_CLOCK_5MHZ;
This seems wrong/unnecessary. This bit is already set.
quoted hunk
+	if (gwdt->has_irq)
+		enable |= WDCR_WDINTR;
+	enable |= WDCR_ENABLE;
+	writel(enable, gwdt->base + FTWDT010_WDCR);
 
 	return 0;
 }
@@ -133,10 +140,6 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	if (IS_ERR(gwdt->base))
 		return PTR_ERR(gwdt->base);
 
-	irq = platform_get_irq(pdev, 0);
-	if (!irq)
-		return -EINVAL;
-
 	gwdt->dev = dev;
 	gwdt->wdd.info = &ftwdt010_wdt_info;
 	gwdt->wdd.ops = &ftwdt010_wdt_ops;
@@ -158,10 +161,14 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 		writel(reg, gwdt->base + FTWDT010_WDCR);
 	}
 
-	ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
-			       "watchdog bark", gwdt);
-	if (ret)
-		return ret;
+	irq = platform_get_irq(pdev, 0);
+	if (irq) {
+		ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
+				       "watchdog bark", gwdt);
+		if (ret)
+			return ret;
+		gwdt->has_irq = true;
+	}
 
 	ret = devm_watchdog_register_device(dev, &gwdt->wdd);
 	if (ret) {
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-14 16:05:36

On Sat, Aug 12, 2017 at 08:43:11PM +0200, Linus Walleij wrote:
The Gemini platform now provides a proper clock look-up for this
and other IPs, so add clock support to the driver. This also aids
in using the same driver with other platforms such as MOXA ART.

The IP has two clock inputs: PCLK (the IP peripheral clock) and
EXTCLK (an external clock). We are a bit elaborate around this:
on Gemini the EXTCLK is used by default today and it's 5MHz, and
on MOXA ART the PCLK is used. On Aspeed the EXTCLK is used and
it's 1MHz. So add some clever code to fall back to platform
defaults if PCLK or EXTCLK is not provided by the device tree.

Take this opportnity to implement .remove() for the driver that
opportunity
quoted hunk
stops the watchdog and disables the clocks.

Add credits that this code is inspired by MOXA ART.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/ftwdt010_wdt.c | 79 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 8 deletions(-)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index ab38a3a89300..680279f5c679 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -5,6 +5,8 @@
  *
  * Inspired by the out-of-tree drivers from OpenWRT:
  * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ * Inspired by the MOXA ART driver from Jonas Jensen:
+ * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
  *
  * 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
@@ -18,9 +20,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/watchdog.h>
+#include <linux/clk.h>
Any chance to maintain alphabetic order with include files ?
quoted hunk
 
 #define FTWDT010_WDCOUNTER	0x0
 #define FTWDT010_WDLOAD		0x4
@@ -29,19 +33,21 @@
 
 #define WDRESTART_MAGIC		0x5AB9
 
-#define WDCR_CLOCK_5MHZ		BIT(4)
+#define WDCR_EXTCLK		BIT(4)
 #define WDCR_WDEXT		BIT(3)
 #define WDCR_WDINTR		BIT(2)
 #define WDCR_SYS_RST		BIT(1)
 #define WDCR_ENABLE		BIT(0)
 
-#define WDT_CLOCK		5000000		/* 5 MHz */
-
 struct ftwdt010_wdt {
 	struct watchdog_device	wdd;
 	struct device		*dev;
 	void __iomem		*base;
 	bool			has_irq;
+	struct clk		*pclk;
+	struct clk		*extclk;
+	unsigned int		clk_freq;
+	bool			use_extclk;
 };
 
 static inline
@@ -55,12 +61,13 @@ static int ftwdt010_wdt_start(struct watchdog_device *wdd)
 	struct ftwdt010_wdt *gwdt = to_ftwdt010_wdt(wdd);
 	u32 enable;
 
-	writel(wdd->timeout * WDT_CLOCK, gwdt->base + FTWDT010_WDLOAD);
+	writel(wdd->timeout * gwdt->clk_freq, gwdt->base + FTWDT010_WDLOAD);
 	writel(WDRESTART_MAGIC, gwdt->base + FTWDT010_WDRESTART);
 	/* set clock before enabling */
-	enable = WDCR_CLOCK_5MHZ | WDCR_SYS_RST;
+	enable = WDCR_SYS_RST;
+	if (gwdt->use_extclk)
+		enable |= WDCR_EXTCLK;
 	writel(enable, gwdt->base + FTWDT010_WDCR);
-	enable |= WDCR_CLOCK_5MHZ;
 	if (gwdt->has_irq)
 		enable |= WDCR_WDINTR;
 	enable |= WDCR_ENABLE;
@@ -125,6 +132,7 @@ static const struct watchdog_info ftwdt010_wdt_info = {
 static int ftwdt010_wdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 	struct resource *res;
 	struct ftwdt010_wdt *gwdt;
 	unsigned int reg;
@@ -140,11 +148,51 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 	if (IS_ERR(gwdt->base))
 		return PTR_ERR(gwdt->base);
 
+	gwdt->use_extclk = of_property_read_bool(np, "faraday,use-extclk");
+
+	gwdt->pclk = devm_clk_get(dev, "PCLK");
+	if (!IS_ERR(gwdt->pclk)) {
devm_clk_get() can return NULL (if the clock subsystem is not enabled).
+		ret = clk_prepare_enable(gwdt->pclk);
Why enable pclk if extclk is used ?
+		if (ret) {
+			dev_err(&pdev->dev, "unable to enable PCLK\n");
+			return ret;
+		}
+		if (!gwdt->use_extclk)
+			gwdt->clk_freq = clk_get_rate(gwdt->pclk);
+	} else {
+		dev_info(dev, "PCLK clock not found assume always-on\n");
Those info messages seem more like debug messages to me. Is this and the message
below about 5MHz clock on Gemini really necessary ?
+	}
+
+	gwdt->extclk = devm_clk_get(dev, "EXTCLK");
+	if (!IS_ERR(gwdt->extclk)) {
devm_clk_get() can return NULL.
+		/* Only enable and get frequency from EXTCLK if it's in use */
+		if (gwdt->use_extclk) {
+			ret = clk_prepare_enable(gwdt->extclk);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"unable to enable EXTCLK\n");
+				return ret;
+			}
+			gwdt->clk_freq = clk_get_rate(gwdt->extclk);
+		}
+	} else {
+		if (of_device_is_compatible(np, "cortina,gemini-watchdog")) {
+			gwdt->clk_freq = 5000000;
+			gwdt->use_extclk = true;
+			dev_info(dev, "assume 5MHz EXTCLK on Gemini\n");
+		}
+	}
+
+	if (gwdt->clk_freq == 0) {
+		dev_err(dev, "no clocking available\n");
+		return -EINVAL;
So far this situation defaulted to 5 MHz (as there was nothing else).
Is this a new restriction or did it just not happen ?

Also, this can at least in theory happen if clk_get_rate() returns 0,
which would leave the clock enabled (although that would be an odd
situation).
+	}
+
 	gwdt->dev = dev;
 	gwdt->wdd.info = &ftwdt010_wdt_info;
 	gwdt->wdd.ops = &ftwdt010_wdt_ops;
 	gwdt->wdd.min_timeout = 1;
-	gwdt->wdd.max_timeout = 0xFFFFFFFF / WDT_CLOCK;
+	gwdt->wdd.max_timeout = UINT_MAX / gwdt->clk_freq;
 	gwdt->wdd.parent = dev;
 
devm_watchdog_register_device() can fail, which would leave the clocks
enabled. Also see below.
quoted hunk
 	/*
@@ -178,7 +226,21 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
 
 	/* Set up platform driver data */
 	platform_set_drvdata(pdev, gwdt);
-	dev_info(dev, "FTWDT010 watchdog driver enabled\n");
+	dev_info(dev, "FTWDT010 watchdog driver @%uHz\n",
+		 gwdt->clk_freq);
+
+	return 0;
+}
+
+static int ftwdt010_wdt_remove(struct platform_device *pdev)
+{
+	struct ftwdt010_wdt *gwdt = platform_get_drvdata(pdev);
+
+	writel(0, gwdt->base + FTWDT010_WDCR);
+	if (!IS_ERR(gwdt->pclk))
+		clk_disable_unprepare(gwdt->pclk);
+	if (!IS_ERR(gwdt->extclk) && gwdt->use_extclk)
+		clk_disable_unprepare(gwdt->extclk);
One of those many situations where devm_clk_prepare_enable() would have
been very useful :-(. This disables the clocks while the watchdog itself
as well as its interrupt handler is still registered. I don't know if this
will have adverse affects, but it makes me quite concerned. Please consider
adding devm_add_action() calls to clean up the clocks. Note that I would
resist replacing all the devm_ functions with non-devm equivalents just
because the clock subsystem doesn't provide the necessary API functions.

Side note: Maybe we _should_ introduce devm_watchdog_clk_prepare_enable()
since this problem affects several watchdog drivers.

Guenter
quoted hunk
 
 	return 0;
 }
@@ -225,6 +287,7 @@ MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
 
 static struct platform_driver ftwdt010_wdt_driver = {
 	.probe		= ftwdt010_wdt_probe,
+	.remove		= ftwdt010_wdt_remove,
 	.driver		= {
 		.name	= "ftwdt010-wdt",
 		.of_match_table = of_match_ptr(ftwdt010_wdt_match),
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 08/11] watchdog: ftwdt010/moxart: Merge MOXA ART into FTWDT010

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-14 16:09:32

On Sat, Aug 12, 2017 at 08:43:15PM +0200, Linus Walleij wrote:
quoted hunk
These two drivers is for the same hardware, the only difference
is that Gemini uses the EXTCLK @5MHz by default (it also works
fine using PCLK) while the MOXA ART is using the PCLK to clock
the watchdog.

Delete the old MOXA ART driver and augment the FTWDT010 to
probe on this platform too, fetching the operating frequency
from the PCLK. Select the driver by default for ARCH_MOXART
to make a smooth transition of the platform.

Signed-off-by: Linus Walleij <redacted>
---
 drivers/watchdog/Kconfig        |  11 +--
 drivers/watchdog/Makefile       |   1 -
 drivers/watchdog/ftwdt010_wdt.c |   1 +
 drivers/watchdog/moxart_wdt.c   | 178 ----------------------------------------
 4 files changed, 2 insertions(+), 189 deletions(-)
 delete mode 100644 drivers/watchdog/moxart_wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fd44a542036a..beef6bb5c6d9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -326,6 +326,7 @@ config FTWDT010_WATCHDOG
 	depends on ARM || COMPILE_TEST
 	select WATCHDOG_CORE
 	default ARCH_GEMINI
+	default ARCH_MOXART
Can one have more than one default statement ? What is the semantics ?
Just making sure that it isn't "last one wins".
quoted hunk
 	help
 	  Say Y here if to include support for the Faraday Technology
 	  FTWDT010 watchdog timer embedded in the Cortina Systems Gemini
@@ -609,16 +610,6 @@ config RETU_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called retu_wdt.
 
-config MOXART_WDT
-	tristate "MOXART watchdog"
-	depends on ARCH_MOXART || COMPILE_TEST
-	help
-	  Say Y here to include Watchdog timer support for the watchdog
-	  existing on the MOXA ART SoC series platforms.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called moxart_wdt.
-
 config SIRFSOC_WATCHDOG
 	tristate "SiRFSOC watchdog"
 	depends on ARCH_SIRF || COMPILE_TEST
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index df91d7db821c..fcab71f0a1c7 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
 obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
 obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
 obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
-obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
 obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
 obj-$(CONFIG_ST_LPC_WATCHDOG) += st_lpc_wdt.o
 obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 7fc865eea28d..912b55e67110 100644
--- a/drivers/watchdog/ftwdt010_wdt.c
+++ b/drivers/watchdog/ftwdt010_wdt.c
@@ -298,6 +298,7 @@ static const struct dev_pm_ops ftwdt010_wdt_dev_pm_ops = {
 static const struct of_device_id ftwdt010_wdt_match[] = {
 	{ .compatible = "faraday,ftwdt010" },
 	{ .compatible = "cortina,gemini-watchdog" },
+	{ .compatible = "moxa,moxart-watchdog" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ftwdt010_wdt_match);
diff --git a/drivers/watchdog/moxart_wdt.c b/drivers/watchdog/moxart_wdt.c
deleted file mode 100644
index 2c4a73d1e214..000000000000
--- a/drivers/watchdog/moxart_wdt.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * MOXA ART SoCs watchdog driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/watchdog.h>
-#include <linux/moduleparam.h>
-
-#define REG_COUNT			0x4
-#define REG_MODE			0x8
-#define REG_ENABLE			0xC
-
-struct moxart_wdt_dev {
-	struct watchdog_device dev;
-	void __iomem *base;
-	unsigned int clock_frequency;
-};
-
-static int heartbeat;
-
-static int moxart_wdt_restart(struct watchdog_device *wdt_dev,
-			      unsigned long action, void *data)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(1, moxart_wdt->base + REG_COUNT);
-	writel(0x5ab9, moxart_wdt->base + REG_MODE);
-	writel(0x03, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_stop(struct watchdog_device *wdt_dev)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(0, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_start(struct watchdog_device *wdt_dev)
-{
-	struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev);
-
-	writel(moxart_wdt->clock_frequency * wdt_dev->timeout,
-	       moxart_wdt->base + REG_COUNT);
-	writel(0x5ab9, moxart_wdt->base + REG_MODE);
-	writel(0x03, moxart_wdt->base + REG_ENABLE);
-
-	return 0;
-}
-
-static int moxart_wdt_set_timeout(struct watchdog_device *wdt_dev,
-				  unsigned int timeout)
-{
-	wdt_dev->timeout = timeout;
-
-	return 0;
-}
-
-static const struct watchdog_info moxart_wdt_info = {
-	.identity       = "moxart-wdt",
-	.options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-			  WDIOF_MAGICCLOSE,
-};
-
-static const struct watchdog_ops moxart_wdt_ops = {
-	.owner          = THIS_MODULE,
-	.start          = moxart_wdt_start,
-	.stop           = moxart_wdt_stop,
-	.set_timeout    = moxart_wdt_set_timeout,
-	.restart        = moxart_wdt_restart,
-};
-
-static int moxart_wdt_probe(struct platform_device *pdev)
-{
-	struct moxart_wdt_dev *moxart_wdt;
-	struct device *dev = &pdev->dev;
-	struct device_node *node = dev->of_node;
-	struct resource *res;
-	struct clk *clk;
-	int err;
-	unsigned int max_timeout;
-	bool nowayout = WATCHDOG_NOWAYOUT;
-
-	moxart_wdt = devm_kzalloc(dev, sizeof(*moxart_wdt), GFP_KERNEL);
-	if (!moxart_wdt)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, moxart_wdt);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	moxart_wdt->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(moxart_wdt->base))
-		return PTR_ERR(moxart_wdt->base);
-
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("%s: of_clk_get failed\n", __func__);
-		return PTR_ERR(clk);
-	}
-
-	moxart_wdt->clock_frequency = clk_get_rate(clk);
-	if (moxart_wdt->clock_frequency == 0) {
-		pr_err("%s: incorrect clock frequency\n", __func__);
-		return -EINVAL;
-	}
-
-	max_timeout = UINT_MAX / moxart_wdt->clock_frequency;
-
-	moxart_wdt->dev.info = &moxart_wdt_info;
-	moxart_wdt->dev.ops = &moxart_wdt_ops;
-	moxart_wdt->dev.timeout = max_timeout;
-	moxart_wdt->dev.min_timeout = 1;
-	moxart_wdt->dev.max_timeout = max_timeout;
-	moxart_wdt->dev.parent = dev;
-
-	watchdog_init_timeout(&moxart_wdt->dev, heartbeat, dev);
-	watchdog_set_nowayout(&moxart_wdt->dev, nowayout);
-	watchdog_set_restart_priority(&moxart_wdt->dev, 128);
-
-	watchdog_set_drvdata(&moxart_wdt->dev, moxart_wdt);
-
-	err = watchdog_register_device(&moxart_wdt->dev);
-	if (err)
-		return err;
-
-	dev_dbg(dev, "Watchdog enabled (heartbeat=%d sec, nowayout=%d)\n",
-		moxart_wdt->dev.timeout, nowayout);
-
-	return 0;
-}
-
-static int moxart_wdt_remove(struct platform_device *pdev)
-{
-	struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev);
-
-	moxart_wdt_stop(&moxart_wdt->dev);
-
-	return 0;
-}
-
-static const struct of_device_id moxart_watchdog_match[] = {
-	{ .compatible = "moxa,moxart-watchdog" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, moxart_watchdog_match);
-
-static struct platform_driver moxart_wdt_driver = {
-	.probe      = moxart_wdt_probe,
-	.remove     = moxart_wdt_remove,
-	.driver     = {
-		.name		= "moxart-watchdog",
-		.of_match_table	= moxart_watchdog_match,
-	},
-};
-module_platform_driver(moxart_wdt_driver);
-
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds");
-
-MODULE_DESCRIPTION("MOXART watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
-- 
2.13.4

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: Linus Walleij <hidden>
Date: 2017-08-24 20:32:22

On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
+     gwdt->pclk = devm_clk_get(dev, "PCLK");
+     if (!IS_ERR(gwdt->pclk)) {
devm_clk_get() can return NULL (if the clock subsystem is not enabled).
That is fine I think? Because if the clock subsysten is not enabled
all the clk_prepare() etc becomes stubs as well and the driver
is happy. I think this is intended.
quoted
+             ret = clk_prepare_enable(gwdt->pclk);
Why enable pclk if extclk is used ?
It is used to clock the silicon in the IP block (so one can access the
registers etc) even if the timer per se uses EXTCLK.

So it must always be enabled.
quoted
+             if (ret) {
+                     dev_err(&pdev->dev, "unable to enable PCLK\n");
+                     return ret;
+             }
+             if (!gwdt->use_extclk)
+                     gwdt->clk_freq = clk_get_rate(gwdt->pclk);
+     } else {
+             dev_info(dev, "PCLK clock not found assume always-on\n");
Those info messages seem more like debug messages to me. Is this and the message
below about 5MHz clock on Gemini really necessary ?
Depends on whether one is pr_info()/dev_info() minimalist or
maximalist or something. I guess the extreme minimalist would be
happiest of their dmesg was 0 lines if all is fine. Maybe it could
just say the Linux version.

I even had the idea to add the subsystem maintainers preference
for this to MAINTAINERS.

I tend to like a bit of blather about the state of things in dmesg,
(as in *info has a purpose) but I'm happy to do whatever the
subsystem maintainer likes.

So I can surely cut a whole slew of them if that is your preference?
quoted
+     gwdt->extclk = devm_clk_get(dev, "EXTCLK");
+     if (!IS_ERR(gwdt->extclk)) {
devm_clk_get() can return NULL.
Same answer: should be fine.
quoted
+     if (gwdt->clk_freq == 0) {
+             dev_err(dev, "no clocking available\n");
+             return -EINVAL;
So far this situation defaulted to 5 MHz (as there was nothing else).
Is this a new restriction or did it just not happen ?
This comes from Jonas' Moxart driver.

I guess this only happens if someone compiles out the
clk subsystem so they get frequency 0 from the stub.

The driver strictly needs this frequency
so we cannot really work without it and it needs to fail
over here.
Also, this can at least in theory happen if clk_get_rate() returns 0,
which would leave the clock enabled (although that would be an odd
situation).
Yeah I should clk_disable_unprepare() on the error path,
thanks. Fixing it.
devm_watchdog_register_device() can fail, which would leave the clocks
enabled. Also see below.
Fixed it.
quoted
+     if (!IS_ERR(gwdt->pclk))
+             clk_disable_unprepare(gwdt->pclk);
+     if (!IS_ERR(gwdt->extclk) && gwdt->use_extclk)
+             clk_disable_unprepare(gwdt->extclk);
One of those many situations where devm_clk_prepare_enable() would have
been very useful :-(. This disables the clocks while the watchdog itself
as well as its interrupt handler is still registered.
Oh hm yeah. I ran into this thing with the IRQs still being
enabled while the clocking get shut off. It is a problem in the
entire kernel. I don't even have a good intuition for what
order the devm_* things get cleaned up, I guess in the
inverse order that one use them in probe()?
I don't know if this
will have adverse affects, but it makes me quite concerned. Please consider
adding devm_add_action() calls to clean up the clocks.
I don't know if that is a very good idea. If we later get proper
devm_* clock disabling functions then that gets messy
to clean up.

Stephen/Mike: what's your opinion?
Note that I would
resist replacing all the devm_ functions with non-devm equivalents just
because the clock subsystem doesn't provide the necessary API functions.
I've seen people do this for this reason though :/
Side note: Maybe we _should_ introduce devm_watchdog_clk_prepare_enable()
since this problem affects several watchdog drivers.
Hmmmmmmmmm a special watchdog primitive may be apropriate.
Dunno what the clk maintainers think?

Stephen/Mike: do you like that or would you rather see a primitive
inside the clock subsystem for this?

Yours,
Linus Walleij

[PATCH 08/11] watchdog: ftwdt010/moxart: Merge MOXA ART into FTWDT010

From: Linus Walleij <hidden>
Date: 2017-08-24 20:34:56

On Mon, Aug 14, 2017 at 6:09 PM, Guenter Roeck [off-list ref] wrote:
quoted
      default ARCH_GEMINI
+     default ARCH_MOXART
Can one have more than one default statement ? What is the semantics ?
Just making sure that it isn't "last one wins".
I would guess logical OR but to be on the safe side, I will
convert these to an explicit default (ARCH_GEMINI || ARCH_MOXART)

Yours,
Linus Walleij

[PATCH 09/11] watchdog: ftwdt010/aspeed: Merge Aspeed into FTWDT010

From: Linus Walleij <hidden>
Date: 2017-08-24 20:41:56

On Mon, Aug 14, 2017 at 5:04 PM, Guenter Roeck [off-list ref] wrote:
On Sat, Aug 12, 2017 at 08:43:16PM +0200, Linus Walleij wrote:
quoted
These two drivers is for the almost the same hardware,
the only differences are:
- The Aspeed IP block has been hacked to use a different
  magic value.
- The Aspeed has hard-wired 1MHz to the EXTCLK and
  apparently even disabled the use of PCLK for clocking
  the block on AST2500.
Confused. I thought the ast2500 is an EC. Am I missing something ?
Sorry I'm confused too now... What is EC?
Can you spell out that acronym, I never heard
it, or forgot it.

Yours,
Linus Walleij

[PATCH 02/11] watchdog: gemini/ftwdt010: rename driver and symbols

From: Linus Walleij <hidden>
Date: 2017-08-24 20:45:27

On Mon, Aug 14, 2017 at 5:01 PM, Guenter Roeck [off-list ref] wrote:
On Sat, Aug 12, 2017 at 08:43:09PM +0200, Linus Walleij wrote:
quoted
-config GEMINI_WATCHDOG
-     tristate "Gemini watchdog"
-     depends on ARCH_GEMINI
+config FTWDT010_WATCHDOG
+     tristate "Faraday Technology FTWDT010 watchdog"
+     depends on ARM || COMPILE_TEST
Did you test this ? I am kind of wary about COMPILE_TEST in watchdog drivers.
I tried to enable that a while ago, and we had to spend a couple of releases
fixing the fallout (even though I had tried to make sure that everything
builds).
Incidentally, yes!

I push my tree to kernelorg where the zeroday autobuilders pick it up
and compile all kind of archs.

I'm pushing the updated patches too.

The big culprit used to be um linux, since it doesn't do MMIO.
But I think that has been solved recently because I don't see
complaints about it anymore.

Yours,
Linus Walleij

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: Stephen Boyd <hidden>
Date: 2017-08-25 23:28:46

On 08/24, Linus Walleij wrote:
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
Side note: Maybe we _should_ introduce devm_watchdog_clk_prepare_enable()
since this problem affects several watchdog drivers.
Hmmmmmmmmm a special watchdog primitive may be apropriate.
Dunno what the clk maintainers think?

Stephen/Mike: do you like that or would you rather see a primitive
inside the clock subsystem for this?
devm_clk_prepare_enable() was already proposed and then the
thread went quiet. Re-kickstart it?

I'd still prefer we just disable clks on clk_put(), but Russell
said we needed to fix all non-common clk implementations of the
clk API to do that and then I forgot about the topic (so
anti-climatic). I'm pretty much OK with us merging the temporary
solution. We can churn again later and remove it all once we
convert everything into one CCF.

I'd prefer we also change common clk framework to actually do the
disable on put though so we flush out any issues early. If the
two things are packaged together I would be ultra happy. It's not
like people are going to convert to CCF just so they can get clk
disable on clk_put() as a feature, but at least we can have it as
a feature.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-27 17:06:41

On Thu, Aug 24, 2017 at 10:32:22PM +0200, Linus Walleij wrote:
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
quoted
+     gwdt->pclk = devm_clk_get(dev, "PCLK");
+     if (!IS_ERR(gwdt->pclk)) {
devm_clk_get() can return NULL (if the clock subsystem is not enabled).
That is fine I think? Because if the clock subsysten is not enabled
all the clk_prepare() etc becomes stubs as well and the driver
is happy. I think this is intended.
If I understand your comment below correctly, the driver won't work
without clock subsystem because the clock frequency would in that case
be 0. Why not catch that situation here, or even better make the driver
depends on the clock subsystem ?
quoted
quoted
+             ret = clk_prepare_enable(gwdt->pclk);
Why enable pclk if extclk is used ?
It is used to clock the silicon in the IP block (so one can access the
registers etc) even if the timer per se uses EXTCLK.

So it must always be enabled.
quoted
quoted
+             if (ret) {
+                     dev_err(&pdev->dev, "unable to enable PCLK\n");
+                     return ret;
+             }
+             if (!gwdt->use_extclk)
+                     gwdt->clk_freq = clk_get_rate(gwdt->pclk);
+     } else {
+             dev_info(dev, "PCLK clock not found assume always-on\n");
Those info messages seem more like debug messages to me. Is this and the message
below about 5MHz clock on Gemini really necessary ?
Depends on whether one is pr_info()/dev_info() minimalist or
maximalist or something. I guess the extreme minimalist would be
happiest of their dmesg was 0 lines if all is fine. Maybe it could
just say the Linux version.

I even had the idea to add the subsystem maintainers preference
for this to MAINTAINERS.

I tend to like a bit of blather about the state of things in dmesg,
(as in *info has a purpose) but I'm happy to do whatever the
subsystem maintainer likes.

So I can surely cut a whole slew of them if that is your preference?
Minimalist.
quoted
quoted
+     gwdt->extclk = devm_clk_get(dev, "EXTCLK");
+     if (!IS_ERR(gwdt->extclk)) {
devm_clk_get() can return NULL.
Same answer: should be fine.
quoted
quoted
+     if (gwdt->clk_freq == 0) {
+             dev_err(dev, "no clocking available\n");
+             return -EINVAL;
So far this situation defaulted to 5 MHz (as there was nothing else).
Is this a new restriction or did it just not happen ?
This comes from Jonas' Moxart driver.

I guess this only happens if someone compiles out the
clk subsystem so they get frequency 0 from the stub.

The driver strictly needs this frequency
so we cannot really work without it and it needs to fail
over here.
Repeating from above, doesn't that mean that the driver depends
on the clock subsystem ? Or am I missong some context ?
quoted
Also, this can at least in theory happen if clk_get_rate() returns 0,
which would leave the clock enabled (although that would be an odd
situation).
Yeah I should clk_disable_unprepare() on the error path,
thanks. Fixing it.
quoted
devm_watchdog_register_device() can fail, which would leave the clocks
enabled. Also see below.
Fixed it.
quoted
quoted
+     if (!IS_ERR(gwdt->pclk))
+             clk_disable_unprepare(gwdt->pclk);
+     if (!IS_ERR(gwdt->extclk) && gwdt->use_extclk)
+             clk_disable_unprepare(gwdt->extclk);
One of those many situations where devm_clk_prepare_enable() would have
been very useful :-(. This disables the clocks while the watchdog itself
as well as its interrupt handler is still registered.
Oh hm yeah. I ran into this thing with the IRQs still being
enabled while the clocking get shut off. It is a problem in the
entire kernel. I don't even have a good intuition for what
order the devm_* things get cleaned up, I guess in the
inverse order that one use them in probe()?
Correct.
quoted
I don't know if this
will have adverse affects, but it makes me quite concerned. Please consider
adding devm_add_action() calls to clean up the clocks.
I don't know if that is a very good idea. If we later get proper
devm_* clock disabling functions then that gets messy
to clean up.
No, it is equivalent.
Stephen/Mike: what's your opinion?
quoted
Note that I would
resist replacing all the devm_ functions with non-devm equivalents just
because the clock subsystem doesn't provide the necessary API functions.
I've seen people do this for this reason though :/
Yes, but that doesn't make it better.

Guenter
quoted
Side note: Maybe we _should_ introduce devm_watchdog_clk_prepare_enable()
since this problem affects several watchdog drivers.
Hmmmmmmmmm a special watchdog primitive may be apropriate.
Dunno what the clk maintainers think?

Stephen/Mike: do you like that or would you rather see a primitive
inside the clock subsystem for this?

Yours,
Linus Walleij

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-27 17:12:52

On Fri, Aug 25, 2017 at 04:28:46PM -0700, Stephen Boyd wrote:
On 08/24, Linus Walleij wrote:
quoted
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
Side note: Maybe we _should_ introduce devm_watchdog_clk_prepare_enable()
since this problem affects several watchdog drivers.
Hmmmmmmmmm a special watchdog primitive may be apropriate.
Dunno what the clk maintainers think?

Stephen/Mike: do you like that or would you rather see a primitive
inside the clock subsystem for this?
devm_clk_prepare_enable() was already proposed and then the
thread went quiet. Re-kickstart it?
It was propsed several times, and each time it went nowhere.
I got the impression that it won't be accepted, presumably because
it can be misused. I have all but given up on it, and I have it on
my task list to replace pretty much each pair of clk_prepare_enable() /
clk_prepare_disable() calls in the watchdog subsystem with
devm_add_action(). Not that I like that "solution", but life
isn't perfect.

Guenter
I'd still prefer we just disable clks on clk_put(), but Russell
said we needed to fix all non-common clk implementations of the
clk API to do that and then I forgot about the topic (so
anti-climatic). I'm pretty much OK with us merging the temporary
solution. We can churn again later and remove it all once we
convert everything into one CCF.

I'd prefer we also change common clk framework to actually do the
disable on put though so we flush out any issues early. If the
two things are packaged together I would be ultra happy. It's not
like people are going to convert to CCF just so they can get clk
disable on clk_put() as a feature, but at least we can have it as
a feature.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

[PATCH 09/11] watchdog: ftwdt010/aspeed: Merge Aspeed into FTWDT010

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-27 17:13:28

On Thu, Aug 24, 2017 at 10:41:56PM +0200, Linus Walleij wrote:
On Mon, Aug 14, 2017 at 5:04 PM, Guenter Roeck [off-list ref] wrote:
quoted
On Sat, Aug 12, 2017 at 08:43:16PM +0200, Linus Walleij wrote:
quoted
These two drivers is for the almost the same hardware,
the only differences are:
- The Aspeed IP block has been hacked to use a different
  magic value.
- The Aspeed has hard-wired 1MHz to the EXTCLK and
  apparently even disabled the use of PCLK for clocking
  the block on AST2500.
Confused. I thought the ast2500 is an EC. Am I missing something ?
Sorry I'm confused too now... What is EC?
Can you spell out that acronym, I never heard
it, or forgot it.
Embedded Controller
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 02/11] watchdog: gemini/ftwdt010: rename driver and symbols

From: linux@roeck-us.net (Guenter Roeck)
Date: 2017-08-27 17:14:37

On Thu, Aug 24, 2017 at 10:45:27PM +0200, Linus Walleij wrote:
On Mon, Aug 14, 2017 at 5:01 PM, Guenter Roeck [off-list ref] wrote:
quoted
On Sat, Aug 12, 2017 at 08:43:09PM +0200, Linus Walleij wrote:
quoted
quoted
-config GEMINI_WATCHDOG
-     tristate "Gemini watchdog"
-     depends on ARCH_GEMINI
+config FTWDT010_WATCHDOG
+     tristate "Faraday Technology FTWDT010 watchdog"
+     depends on ARM || COMPILE_TEST
Did you test this ? I am kind of wary about COMPILE_TEST in watchdog drivers.
I tried to enable that a while ago, and we had to spend a couple of releases
fixing the fallout (even though I had tried to make sure that everything
builds).
Incidentally, yes!
Ok. Note that I though that too, only 0day didn't pick up all corner cases.

Guenter
I push my tree to kernelorg where the zeroday autobuilders pick it up
and compile all kind of archs.

I'm pushing the updated patches too.

The big culprit used to be um linux, since it doesn't do MMIO.
But I think that has been solved recently because I don't see
complaints about it anymore.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: Linus Walleij <hidden>
Date: 2017-10-10 19:51:26

On Sun, Aug 27, 2017 at 7:06 PM, Guenter Roeck [off-list ref] wrote:
On Thu, Aug 24, 2017 at 10:32:22PM +0200, Linus Walleij wrote:
quoted
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
quoted
+     gwdt->pclk = devm_clk_get(dev, "PCLK");
+     if (!IS_ERR(gwdt->pclk)) {
devm_clk_get() can return NULL (if the clock subsystem is not enabled).
That is fine I think? Because if the clock subsysten is not enabled
all the clk_prepare() etc becomes stubs as well and the driver
is happy. I think this is intended.
If I understand your comment below correctly, the driver won't work
without clock subsystem because the clock frequency would in that case
be 0. Why not catch that situation here, or even better make the driver
depends on the clock subsystem ?
OK fair enough I can do that.

I think Aspeed is merging its clock driver this kernel cycle
so all variant SoCs actually have clocks.
quoted
The driver strictly needs this frequency
so we cannot really work without it and it needs to fail
over here.
Repeating from above, doesn't that mean that the driver depends
on the clock subsystem ? Or am I missong some context ?
Usually in the kernel, it is acceptable to let stub clocks
kick in when compiling out the clock subsystem.

I think people assume that in this state, all clocks are simply
turned on and at nominal speed, all over the place. So it
usually doesn't matter that it gets compiled out.

But in a sense that is simplistic and as this driver shows
we really do depend on the clocks to run some business
like timers, so in practice it is a bad idea. Clocksources
definately cannot live without their clocks for example.
So I think strictly requireing it is OK.
quoted
quoted
Note that I would
resist replacing all the devm_ functions with non-devm equivalents just
because the clock subsystem doesn't provide the necessary API functions.
I've seen people do this for this reason though :/
Yes, but that doesn't make it better.
Stephen Boyd [off-list ref] wrote:
I'd still prefer we just disable clks on clk_put(),
Which means that devm_clk_get() will do the job
implicitly already.
but Russell
said we needed to fix all non-common clk implementations of the
clk API to do that and then I forgot about the topic (so
anti-climatic). I'm pretty much OK with us merging the temporary
solution.
I guess that means the watchdog-local hack that
Guenther suggested.

But I'm not in any hurry. Instead of solving the simple problem,
why not solve the supercomplicated problem.

So the task is to look over all non generic clock implementations
and make them conform to disabling the clocks on clk_put().
No big deal. (Famous last words.)

How many local clock implementations can there be?
I will look into it.

Yours,
Linus Walleij

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: Linus Walleij <hidden>
Date: 2017-10-10 20:06:48

So need info from Joel Stanley here:

On Tue, Oct 10, 2017 at 9:51 PM, Linus Walleij [off-list ref] wrote:
On Sun, Aug 27, 2017 at 7:06 PM, Guenter Roeck [off-list ref] wrote:
quoted
On Thu, Aug 24, 2017 at 10:32:22PM +0200, Linus Walleij wrote:
quoted
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
If I understand your comment below correctly, the driver won't work
without clock subsystem because the clock frequency would in that case
be 0. Why not catch that situation here, or even better make the driver
depends on the clock subsystem ?
OK fair enough I can do that.

I think Aspeed is merging its clock driver this kernel cycle
so all variant SoCs actually have clocks.
So when I later in the patch series convert Aspeed to use this driver
we get a problem because Joel is currently working on the clock
driver for Aspeed and it's not ready for merge yet as it looks.

I can of course wait with the Aspeed conversion to use the common
driver.

Also I can slap in a fixed-rate clock in the device tree @1 MHz.
But that is cheating.

So I guess I rest the Aspeed conversion.

Joel: does your clock patch set cover the 1MHz used by
the watchdog EXTCLK?

Yours,
Linus Walleij

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Linus Walleij <hidden>
Date: 2017-10-10 20:09:52

On Sat, Aug 12, 2017 at 8:43 PM, Linus Walleij [off-list ref] wrote:
This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired so to obtain the frequency from it, it needs to
be present in the device tree, and for completeness the
PCLK should also be referenced and enabled anyways.

Take this opportunity to add the "faraday,ftwdt010"
compatible as fallback to the watchdog IP blocks.

Signed-off-by: Linus Walleij <redacted>
Joel could you merge this through the Aspeed tree? I think
the compatible string is completely uncontroversial
(binding ACKed) to add and all should just work fine so we
can slap in "EXTCLK" later as well.

Yours,
Linus Walleij

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Andrew Jeffery <hidden>
Date: 2017-10-11 03:48:06

On Sat, 2017-08-12 at 20:43 +0200, Linus Walleij wrote:
This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired
This is true for the AST2400, but not the AST2500 where the only option
is EXTCLK (1MHz).
quoted hunk
 so to obtain the frequency from it, it needs to
be present in the device tree, and for completeness the
PCLK should also be referenced and enabled anyways.

Take this opportunity to add the "faraday,ftwdt010"
compatible as fallback to the watchdog IP blocks.
quoted
Signed-off-by: Linus Walleij <redacted>
---
?arch/arm/boot/dts/aspeed-g4.dtsi |??7 +++++--
?arch/arm/boot/dts/aspeed-g5.dtsi | 12 +++++++++---
?2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index 8a04c7e2d818..23b100383c15 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -895,16 +895,19 @@
quoted
?			};
?
quoted
quoted
?			wdt1: wdt at 1e785000 {
-				compatible = "aspeed,ast2400-wdt";
+				compatible = "aspeed,ast2400-wdt", "faraday,ftwdt010";
?				reg = <0x1e785000 0x1c>;
?				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
?			};
?
quoted
quoted
?			wdt2: wdt at 1e785020 {
-				compatible = "aspeed,ast2400-wdt";
+				compatible = "aspeed,ast2400-wdt", "faraday,ftwdt010";
?				reg = <0x1e785020 0x1c>;
?				interrupts = <27>;
?				clocks = <&clk_apb>;
+				clock-names = "PCLK";
?				status = "disabled";
?			};
?
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 9cffe347b828..2322d72cd8a9 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -1003,21 +1003,27 @@
?
?
quoted
quoted
?			wdt1: wdt at 1e785000 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
?				reg = <0x1e785000 0x20>;
?				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
Given the comment above, shouldn't we be doing something like the
following instead for each of the watchdogs?

+				faraday,use-extclk;
+				clock-names = "EXTCLK";

Andrew
?			};
?
quoted
quoted
?			wdt2: wdt at 1e785020 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
?				reg = <0x1e785020 0x20>;
?				interrupts = <27>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
?				status = "disabled";
?			};
?
quoted
quoted
?			wdt3: wdt at 1e785040 {
-				compatible = "aspeed,ast2500-wdt";
+				compatible = "aspeed,ast2500-wdt", "faraday,ftwdt010";
?				reg = <0x1e785040 0x20>;
+				clocks = <&clk_apb>;
+				clock-names = "PCLK";
?				status = "disabled";
?			};
?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171011/7cd46879/attachment.sig>

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Linus Walleij <hidden>
Date: 2017-10-11 06:32:49

On Wed, Oct 11, 2017 at 5:48 AM, Andrew Jeffery [off-list ref] wrote:
On Sat, 2017-08-12 at 20:43 +0200, Linus Walleij wrote:
quoted
This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired
This is true for the AST2400, but not the AST2500 where the only option
is EXTCLK (1MHz).
The IP block/cell certainly has a PCLK even if it cannot be used
to drive the watchdog timer. It is necessary to interface the
SoC interconnect.
quoted
quoted
+                           clocks = <&clk_apb>;
+                             clock-names = "PCLK";
Given the comment above, shouldn't we be doing something like the
following instead for each of the watchdogs?

+                               faraday,use-extclk;
+                               clock-names = "EXTCLK";
So that will be added too, later, when there is a 1MHz clock
to reference in the device tree. I guess after Joel's patches.

Yours,
Linus Walleij

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Andrew Jeffery <hidden>
Date: 2017-10-11 07:14:54

On Wed, 2017-10-11 at 08:32 +0200, Linus Walleij wrote:
quoted
On Wed, Oct 11, 2017 at 5:48 AM, Andrew Jeffery [off-list ref] wrote:
On Sat, 2017-08-12 at 20:43 +0200, Linus Walleij wrote:
quoted
This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired
This is true for the AST2400, but not the AST2500 where the only option
is EXTCLK (1MHz).
The IP block/cell certainly has a PCLK even if it cannot be used
to drive the watchdog timer. It is necessary to interface the
SoC interconnect.
Hah, yep, brain-fade.

Cheers,

Andrew
quoted
quoted
quoted
+???????????????????????????clocks = <&clk_apb>;
+?????????????????????????????clock-names = "PCLK";
Given the comment above, shouldn't we be doing something like the
following instead for each of the watchdogs?

+???????????????????????????????faraday,use-extclk;
+???????????????????????????????clock-names = "EXTCLK";
So that will be added too, later, when there is a 1MHz clock
to reference in the device tree. I guess after Joel's patches.

Yours,
Linus Walleij
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171011/d867a068/attachment-0001.sig>

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: joel@jms.id.au (Joel Stanley)
Date: 2017-10-12 03:37:30

On Wed, Oct 11, 2017 at 4:09 AM, Linus Walleij [off-list ref] wrote:
On Sat, Aug 12, 2017 at 8:43 PM, Linus Walleij [off-list ref] wrote:
quoted
This adds the PCLK clock to the Aspeed watchdog blocks.
I am not directly familiar with the Aspeed clocking, but
since the IP is derived from Faraday FTWDT010 it probably
has the ability to run the watchdog on the PCLK if
desired so to obtain the frequency from it, it needs to
be present in the device tree, and for completeness the
PCLK should also be referenced and enabled anyways.

Take this opportunity to add the "faraday,ftwdt010"
compatible as fallback to the watchdog IP blocks.

Signed-off-by: Linus Walleij <redacted>
Joel could you merge this through the Aspeed tree? I think
the compatible string is completely uncontroversial
(binding ACKed) to add and all should just work fine so we
can slap in "EXTCLK" later as well.
How do the clock-names work? I have been writing the aspeed clk driver
and updating the bindings without clock names, and instead using a
identifier in phandle to reference which clock the device wants.

eg:

 clocks = <&syscon 10>;

(I'm travelling over the next few weeks so my replies might be delayed)

Cheers,

Joel

[PATCH 04/11] watchdog: ftwdt010: Add clock support

From: joel@jms.id.au (Joel Stanley)
Date: 2017-10-12 03:39:50

On Wed, Oct 11, 2017 at 4:06 AM, Linus Walleij [off-list ref] wrote:
So need info from Joel Stanley here:

On Tue, Oct 10, 2017 at 9:51 PM, Linus Walleij [off-list ref] wrote:
quoted
On Sun, Aug 27, 2017 at 7:06 PM, Guenter Roeck [off-list ref] wrote:
quoted
On Thu, Aug 24, 2017 at 10:32:22PM +0200, Linus Walleij wrote:
quoted
On Mon, Aug 14, 2017 at 6:05 PM, Guenter Roeck [off-list ref] wrote:
quoted
quoted
If I understand your comment below correctly, the driver won't work
without clock subsystem because the clock frequency would in that case
be 0. Why not catch that situation here, or even better make the driver
depends on the clock subsystem ?
OK fair enough I can do that.

I think Aspeed is merging its clock driver this kernel cycle
so all variant SoCs actually have clocks.
So when I later in the patch series convert Aspeed to use this driver
we get a problem because Joel is currently working on the clock
driver for Aspeed and it's not ready for merge yet as it looks.

I can of course wait with the Aspeed conversion to use the common
driver.

Also I can slap in a fixed-rate clock in the device tree @1 MHz.
But that is cheating.
All of our clocks in the device tree are cheating at the moment :)
So I guess I rest the Aspeed conversion.
Joel: does your clock patch set cover the 1MHz used by
the watchdog EXTCLK?
It doesn't; none of the documentation I have describes where it comes
from. I will add something in the next iteration.

Cheers,

Joel

[PATCH 11/11] ARM: dts: Add PCLK to the Aspeed watchdogs

From: Linus Walleij <hidden>
Date: 2017-10-12 07:35:42

On Thu, Oct 12, 2017 at 5:37 AM, Joel Stanley [off-list ref] wrote:
On Wed, Oct 11, 2017 at 4:09 AM, Linus Walleij [off-list ref] wrote:
quoted
Joel could you merge this through the Aspeed tree? I think
the compatible string is completely uncontroversial
(binding ACKed) to add and all should just work fine so we
can slap in "EXTCLK" later as well.
How do the clock-names work? I have been writing the aspeed clk driver
and updating the bindings without clock names, and instead using a
identifier in phandle to reference which clock the device wants.

eg:

 clocks = <&syscon 10>;
This works fine as long as there is just one clock.

clocks = <&syscon 10>, <&syscon 11>, <&syscon 12>;

becomes a problem, right?

clk_get() has this signature:
struct clk *clk_get(struct device *dev, const char *id);

So clk_get(dev, NULL); will return <&syscon 10>;

How to get the rest?

clocks = <&syscon 10>, <&syscon 11>, <&syscon 12>;
clock-names = "FOO", "BAR", "BAZ";

clk_get(dev, "BAR");

gets the second clock.

Yours,
Linus Walleij
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help