* [PATCH 2/5 v2] watchdog: gemini/ftwdt010: rename driver and symbols
2017-10-16 20:54 [PATCH 1/5 v2] watchdog: gemini/ftwdt010: rename DT bindings Linus Walleij
@ 2017-10-16 20:54 ` Linus Walleij
2017-10-22 17:18 ` [2/5,v2] " Guenter Roeck
2017-10-16 20:54 ` [PATCH 3/5 v2] watchdog: ftwdt010: Make interrupt optional Linus Walleij
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Linus Walleij @ 2017-10-16 20:54 UTC (permalink / raw)
To: linux-arm-kernel
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 this driver by default for the Gemini, it is a sensible
driver to always have enabled.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Fixed speling in commit message, rebased.
---
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.6
^ permalink raw reply related [flat|nested] 10+ messages in thread* [2/5,v2] watchdog: gemini/ftwdt010: rename driver and symbols
2017-10-16 20:54 ` [PATCH 2/5 v2] watchdog: gemini/ftwdt010: rename driver and symbols Linus Walleij
@ 2017-10-22 17:18 ` Guenter Roeck
0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2017-10-22 17:18 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Oct 16, 2017 at 10:54:24PM +0200, Linus Walleij wrote:
> 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 this driver by default for the Gemini, it is a sensible
> driver to always have enabled.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> ---
> ChangeLog v1->v2:
> - Fixed speling in commit message, rebased.
> ---
> 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");
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/5 v2] watchdog: ftwdt010: Make interrupt optional
2017-10-16 20:54 [PATCH 1/5 v2] watchdog: gemini/ftwdt010: rename DT bindings Linus Walleij
2017-10-16 20:54 ` [PATCH 2/5 v2] watchdog: gemini/ftwdt010: rename driver and symbols Linus Walleij
@ 2017-10-16 20:54 ` Linus Walleij
2017-10-22 17:19 ` [3/5,v2] " Guenter Roeck
2017-10-16 20:54 ` [PATCH 4/5 v2] watchdog: ftwdt010: Add clock support Linus Walleij
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Linus Walleij @ 2017-10-16 20:54 UTC (permalink / raw)
To: linux-arm-kernel
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 <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Fix surplus flag assignment of enable |= WDCR_CLOCK_5MHZ
---
drivers/watchdog/ftwdt010_wdt.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index 637ffd812f0b..a9c2912ee280 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,17 @@ 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);
+ if (gwdt->has_irq)
+ enable |= WDCR_WDINTR;
+ enable |= WDCR_ENABLE;
+ writel(enable, gwdt->base + FTWDT010_WDCR);
return 0;
}
@@ -133,10 +139,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 +160,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.6
^ permalink raw reply related [flat|nested] 10+ messages in thread* [3/5,v2] watchdog: ftwdt010: Make interrupt optional
2017-10-16 20:54 ` [PATCH 3/5 v2] watchdog: ftwdt010: Make interrupt optional Linus Walleij
@ 2017-10-22 17:19 ` Guenter Roeck
0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2017-10-22 17:19 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Oct 16, 2017 at 10:54:25PM +0200, Linus Walleij wrote:
> 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 <linus.walleij@linaro.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> ---
> ChangeLog v1->v2:
> - Fix surplus flag assignment of enable |= WDCR_CLOCK_5MHZ
> ---
> drivers/watchdog/ftwdt010_wdt.c | 30 ++++++++++++++++++------------
> 1 file changed, 18 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
> index 637ffd812f0b..a9c2912ee280 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,17 @@ 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);
> + if (gwdt->has_irq)
> + enable |= WDCR_WDINTR;
> + enable |= WDCR_ENABLE;
> + writel(enable, gwdt->base + FTWDT010_WDCR);
>
> return 0;
> }
> @@ -133,10 +139,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 +160,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) {
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/5 v2] watchdog: ftwdt010: Add clock support
2017-10-16 20:54 [PATCH 1/5 v2] watchdog: gemini/ftwdt010: rename DT bindings Linus Walleij
2017-10-16 20:54 ` [PATCH 2/5 v2] watchdog: gemini/ftwdt010: rename driver and symbols Linus Walleij
2017-10-16 20:54 ` [PATCH 3/5 v2] watchdog: ftwdt010: Make interrupt optional Linus Walleij
@ 2017-10-16 20:54 ` Linus Walleij
2017-10-22 17:30 ` [4/5,v2] " Guenter Roeck
2017-10-16 20:54 ` [PATCH 5/5 v2] watchdog: ftwdt010: Add restart support Linus Walleij
2017-10-22 17:11 ` [1/5,v2] watchdog: gemini/ftwdt010: rename DT bindings Guenter Roeck
4 siblings, 1 reply; 10+ messages in thread
From: Linus Walleij @ 2017-10-16 20:54 UTC (permalink / raw)
To: linux-arm-kernel
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 opportunity 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 <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Strictly require the clock framework
- Sort header files in alphabetic order
- Fix the error path to properly disable the clocks
- Fix spelling in commit message
- Be minimalist with informational messages and cut down
on error messages
---
drivers/watchdog/Kconfig | 1 +
drivers/watchdog/ftwdt010_wdt.c | 79 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fd44a542036a..245cff03c992 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -324,6 +324,7 @@ config 977_WATCHDOG
config FTWDT010_WATCHDOG
tristate "Faraday Technology FTWDT010 watchdog"
depends on ARM || COMPILE_TEST
+ depends on COMMON_CLK
select WATCHDOG_CORE
default ARCH_GEMINI
help
diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
index a9c2912ee280..21c3ac7f557a 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
@@ -12,12 +14,14 @@
*/
#include <linux/bitops.h>
+#include <linux/clk.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#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>
@@ -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,10 +61,12 @@ 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);
if (gwdt->has_irq)
enable |= WDCR_WDINTR;
@@ -124,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;
@@ -139,11 +148,40 @@ 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))
+ return PTR_ERR(gwdt->pclk);
+ ret = clk_prepare_enable(gwdt->pclk);
+ if (ret)
+ return ret;
+ if (!gwdt->use_extclk)
+ gwdt->clk_freq = clk_get_rate(gwdt->pclk);
+
+ /* Only enable and get frequency from EXTCLK if it's in use */
+ if (gwdt->use_extclk) {
+ gwdt->extclk = devm_clk_get(dev, "EXTCLK");
+ if (IS_ERR(gwdt->extclk)) {
+ ret = PTR_ERR(gwdt->extclk);
+ goto out_disable_pclk;
+ }
+ ret = clk_prepare_enable(gwdt->extclk);
+ if (ret)
+ goto out_disable_pclk;
+ gwdt->clk_freq = clk_get_rate(gwdt->extclk);
+ }
+
+ if (gwdt->clk_freq == 0) {
+ ret = -EINVAL;
+ goto out_disable_extclk;
+ }
+
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;
/*
@@ -165,19 +203,41 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
"watchdog bark", gwdt);
if (ret)
- return ret;
+ goto out_disable_extclk;
gwdt->has_irq = true;
}
ret = devm_watchdog_register_device(dev, &gwdt->wdd);
if (ret) {
dev_err(&pdev->dev, "failed to register watchdog\n");
- return ret;
+ goto out_disable_extclk;
}
/* 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;
+
+out_disable_extclk:
+ if (gwdt->use_extclk)
+ clk_disable_unprepare(gwdt->extclk);
+out_disable_pclk:
+ if (!IS_ERR(gwdt->pclk))
+ clk_disable_unprepare(gwdt->pclk);
+
+ return ret;
+}
+
+static int ftwdt010_wdt_remove(struct platform_device *pdev)
+{
+ struct ftwdt010_wdt *gwdt = platform_get_drvdata(pdev);
+
+ writel(0, gwdt->base + FTWDT010_WDCR);
+ clk_disable_unprepare(gwdt->pclk);
+ if (gwdt->use_extclk)
+ clk_disable_unprepare(gwdt->extclk);
return 0;
}
@@ -224,6 +284,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.6
^ permalink raw reply related [flat|nested] 10+ messages in thread* [4/5,v2] watchdog: ftwdt010: Add clock support
2017-10-16 20:54 ` [PATCH 4/5 v2] watchdog: ftwdt010: Add clock support Linus Walleij
@ 2017-10-22 17:30 ` Guenter Roeck
0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2017-10-22 17:30 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Oct 16, 2017 at 10:54:26PM +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.
>
Am I missing something ? The code suggests that PCLK is mandatory.
+ gwdt->pclk = devm_clk_get(dev, "PCLK");
+ if (IS_ERR(gwdt->pclk))
+ return PTR_ERR(gwdt->pclk);
> Take this opportunity 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 <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - Strictly require the clock framework
> - Sort header files in alphabetic order
> - Fix the error path to properly disable the clocks
> - Fix spelling in commit message
> - Be minimalist with informational messages and cut down
> on error messages
> ---
> drivers/watchdog/Kconfig | 1 +
> drivers/watchdog/ftwdt010_wdt.c | 79 ++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 71 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index fd44a542036a..245cff03c992 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -324,6 +324,7 @@ config 977_WATCHDOG
> config FTWDT010_WATCHDOG
> tristate "Faraday Technology FTWDT010 watchdog"
> depends on ARM || COMPILE_TEST
> + depends on COMMON_CLK
> select WATCHDOG_CORE
> default ARCH_GEMINI
> help
> diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c
> index a9c2912ee280..21c3ac7f557a 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
> @@ -12,12 +14,14 @@
> */
>
> #include <linux/bitops.h>
> +#include <linux/clk.h>
> #include <linux/init.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> #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>
> @@ -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,10 +61,12 @@ 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);
> if (gwdt->has_irq)
> enable |= WDCR_WDINTR;
> @@ -124,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;
> @@ -139,11 +148,40 @@ 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");
Documentation and Ack from Rob required.
> +
> + gwdt->pclk = devm_clk_get(dev, "PCLK");
> + if (IS_ERR(gwdt->pclk))
> + return PTR_ERR(gwdt->pclk);
> + ret = clk_prepare_enable(gwdt->pclk);
> + if (ret)
> + return ret;
> + if (!gwdt->use_extclk)
> + gwdt->clk_freq = clk_get_rate(gwdt->pclk);
else case to the is statement below ?
> +
> + /* Only enable and get frequency from EXTCLK if it's in use */
> + if (gwdt->use_extclk) {
Does this use case still require pclk ?
> + gwdt->extclk = devm_clk_get(dev, "EXTCLK");
> + if (IS_ERR(gwdt->extclk)) {
> + ret = PTR_ERR(gwdt->extclk);
> + goto out_disable_pclk;
> + }
> + ret = clk_prepare_enable(gwdt->extclk);
> + if (ret)
> + goto out_disable_pclk;
> + gwdt->clk_freq = clk_get_rate(gwdt->extclk);
> + }
> +
> + if (gwdt->clk_freq == 0) {
> + ret = -EINVAL;
> + goto out_disable_extclk;
Yet another use case of the rejected devm_clk_prepare_enable() :-(.
> + }
> +
> 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;
>
> /*
> @@ -165,19 +203,41 @@ static int ftwdt010_wdt_probe(struct platform_device *pdev)
> ret = devm_request_irq(dev, irq, ftwdt010_wdt_interrupt, 0,
> "watchdog bark", gwdt);
> if (ret)
> - return ret;
> + goto out_disable_extclk;
> gwdt->has_irq = true;
> }
>
> ret = devm_watchdog_register_device(dev, &gwdt->wdd);
> if (ret) {
> dev_err(&pdev->dev, "failed to register watchdog\n");
> - return ret;
> + goto out_disable_extclk;
> }
>
> /* 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;
> +
> +out_disable_extclk:
> + if (gwdt->use_extclk)
> + clk_disable_unprepare(gwdt->extclk);
> +out_disable_pclk:
> + if (!IS_ERR(gwdt->pclk))
> + clk_disable_unprepare(gwdt->pclk);
> +
> + return ret;
> +}
> +
> +static int ftwdt010_wdt_remove(struct platform_device *pdev)
> +{
> + struct ftwdt010_wdt *gwdt = platform_get_drvdata(pdev);
> +
> + writel(0, gwdt->base + FTWDT010_WDCR);
> + clk_disable_unprepare(gwdt->pclk);
> + if (gwdt->use_extclk)
> + clk_disable_unprepare(gwdt->extclk);
>
> return 0;
> }
> @@ -224,6 +284,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),
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/5 v2] watchdog: ftwdt010: Add restart support
2017-10-16 20:54 [PATCH 1/5 v2] watchdog: gemini/ftwdt010: rename DT bindings Linus Walleij
` (2 preceding siblings ...)
2017-10-16 20:54 ` [PATCH 4/5 v2] watchdog: ftwdt010: Add clock support Linus Walleij
@ 2017-10-16 20:54 ` Linus Walleij
2017-10-22 17:31 ` [5/5,v2] " Guenter Roeck
2017-10-22 17:11 ` [1/5,v2] watchdog: gemini/ftwdt010: rename DT bindings Guenter Roeck
4 siblings, 1 reply; 10+ messages in thread
From: Linus Walleij @ 2017-10-16 20:54 UTC (permalink / raw)
To: linux-arm-kernel
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 <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Rebased, no changes.
---
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 21c3ac7f557a..0be7c2db642d 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,
};
@@ -190,6 +207,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.6
^ permalink raw reply related [flat|nested] 10+ messages in thread* [5/5,v2] watchdog: ftwdt010: Add restart support
2017-10-16 20:54 ` [PATCH 5/5 v2] watchdog: ftwdt010: Add restart support Linus Walleij
@ 2017-10-22 17:31 ` Guenter Roeck
0 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2017-10-22 17:31 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Oct 16, 2017 at 10:54:27PM +0200, Linus Walleij wrote:
> 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 <linus.walleij@linaro.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> ---
> ChangeLog v1->v2:
> - Rebased, no changes.
> ---
> 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 21c3ac7f557a..0be7c2db642d 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,
> };
>
> @@ -190,6 +207,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) {
^ permalink raw reply [flat|nested] 10+ messages in thread
* [1/5,v2] watchdog: gemini/ftwdt010: rename DT bindings
2017-10-16 20:54 [PATCH 1/5 v2] watchdog: gemini/ftwdt010: rename DT bindings Linus Walleij
` (3 preceding siblings ...)
2017-10-16 20:54 ` [PATCH 5/5 v2] watchdog: ftwdt010: Add restart support Linus Walleij
@ 2017-10-22 17:11 ` Guenter Roeck
4 siblings, 0 replies; 10+ messages in thread
From: Guenter Roeck @ 2017-10-22 17:11 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Oct 16, 2017 at 10:54:23PM +0200, Linus Walleij wrote:
> The device tree bindings are in two copies and also should be
> consolidated into a single Faraday Technology FTWDT010
> binding since we uncovered that this IP part is a standard
> IP from Faraday.
>
> Cc: devicetree at vger.kernel.org
> Acked-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> ---
> ChangeLog v1->v2:
> - Collect Rob's ACK.
> ---
> .../bindings/watchdog/cortina,gemini-watchdog.txt | 17 -----------------
> ...{cortina,gemin-watchdog.txt => faraday,ftwdt010.txt} | 11 ++++++++---
> 2 files changed, 8 insertions(+), 20 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt
> rename Documentation/devicetree/bindings/watchdog/{cortina,gemin-watchdog.txt => faraday,ftwdt010.txt} (55%)
>
> diff --git a/Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt b/Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt
> deleted file mode 100644
> index bc4b865d178b..000000000000
> --- a/Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -Cortina Systems Gemini SoC Watchdog
> -
> -Required properties:
> -- compatible : must be "cortina,gemini-watchdog"
> -- reg : shall contain base register location and length
> -- interrupts : shall contain the interrupt for the watchdog
> -
> -Optional properties:
> -- timeout-sec : the default watchdog timeout in seconds.
> -
> -Example:
> -
> -watchdog at 41000000 {
> - compatible = "cortina,gemini-watchdog";
> - reg = <0x41000000 0x1000>;
> - interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
> -};
> diff --git a/Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt
> similarity index 55%
> rename from Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt
> rename to Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt
> index bc4b865d178b..9ecdb502e605 100644
> --- a/Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt
> +++ b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt
> @@ -1,7 +1,12 @@
> -Cortina Systems Gemini SoC Watchdog
> +Faraday Technology FTWDT010 watchdog
> +
> +This is an IP part from Faraday Technology found in the Gemini
> +SoCs and others.
>
> Required properties:
> -- compatible : must be "cortina,gemini-watchdog"
> +- compatible : must be one of
> + "faraday,ftwdt010"
> + "cortina,gemini-watchdog", "faraday,ftwdt010"
> - reg : shall contain base register location and length
> - interrupts : shall contain the interrupt for the watchdog
>
> @@ -11,7 +16,7 @@ Optional properties:
> Example:
>
> watchdog at 41000000 {
> - compatible = "cortina,gemini-watchdog";
> + compatible = "faraday,ftwdt010";
> reg = <0x41000000 0x1000>;
> interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
> };
^ permalink raw reply [flat|nested] 10+ messages in thread