watchdog: gemini/ftwdt010: rename DT bindings
Subsystems (2)
PATCH v2 1/5 watchdog: gemini/ftwdt010: rename DT bindings
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.
---
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%)Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt deleted +0 -17
@@ -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>; -};
Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt renamed from Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt +8 -3
@@ -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>; };
Signature · 1 line
2.13.6
PATCH v2 2/5 watchdog: gemini/ftwdt010: rename driver and symbols
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.
---
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%)drivers/watchdog/Kconfig +8 -6
@@ -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"
drivers/watchdog/Makefile +1 -1
@@ -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
drivers/watchdog/ftwdt010_wdt.c renamed from drivers/watchdog/gemini_wdt.c +59 -58
245 lines not on this page · raw message
Signature · 1 line
2.13.6
Guenter Roeck
maintainerPATCH v2 2/5 watchdog: gemini/ftwdt010: rename driver and symbols
Quoted 9 lines · Linus Walleij
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 <[email protected]>
Quoted 311 lines
---
ChangeLogv1->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%)drivers/watchdog/Kconfig +8
-6@@ -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"drivers/watchdog/Makefile +1
-1@@ -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.odrivers/watchdog/ftwdt010_wdt.c renamed from drivers/watchdog/gemini_wdt.c +59
-58@@ -1,5 +1,5 @@/* -* Watchdog driver for Cortina Systems Gemini SoC +* Watchdog driver for Faraday Technology FTWDT010 * * Copyright (C) 2017 Linus Walleij <[email protected]> * @@ -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" );
PATCH v2 3/5 watchdog: ftwdt010: Make interrupt optional
In reply to Linus WalleijThe 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.
---
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(-)
drivers/watchdog/ftwdt010_wdt.c +18 -12
@@ -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) {
Signature · 1 line
2.13.6
Guenter Roeck
maintainerPATCH v2 3/5 watchdog: ftwdt010: Make interrupt optional
Quoted 10 lines · Linus Walleij
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 <[email protected]>
Quoted 80 lines
---
ChangeLogv1->v2:
- Fix surplus flag assignment of enable |=WDCR_CLOCK_5MHZ--- drivers/watchdog/ftwdt010_wdt.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)drivers/watchdog/ftwdt010_wdt.c +18
-12@@ -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) {
PATCH v2 4/5 watchdog: ftwdt010: Add clock support
In reply to Linus WalleijThe 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.
---
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(-)
drivers/watchdog/Kconfig +1 -0
@@ -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
drivers/watchdog/ftwdt010_wdt.c +70 -9
159 lines not on this page · raw message
Signature · 1 line
2.13.6
Guenter Roeck
maintainerPATCH v2 4/5 watchdog: ftwdt010: Add clock support
Quoted 11 lines · Linus Walleij
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);
Quoted 108 lines
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 <[email protected]>---
ChangeLogv1->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(-)drivers/watchdog/Kconfig +1
-0@@ -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 helpdrivers/watchdog/ftwdt010_wdt.c +14
-5@@ -5,6 +5,8 @@* * Inspired by the out-of-tree drivers from OpenWRT: * Copyright (C) 2009 Paulius Zaleckas <[email protected]> +* Inspired by the MOXA ART driver from Jonas Jensen: +* Copyright (C) 2013 Jonas Jensen <[email protected]> * * 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;
drivers/watchdog/ftwdt010_wdt.c static int ftwdt010_wdt_probe(struct platform_device *pdev) · line 151
Quoted 4 lines
drivers/watchdog/ftwdt010_wdt.c +1
-0@@ -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.
drivers/watchdog/ftwdt010_wdt.c static int ftwdt010_wdt_probe(struct platform_device *pdev) · line 160
Quoted 9 lines
drivers/watchdog/ftwdt010_wdt.c +9
-0+ + 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 ?
drivers/watchdog/ftwdt010_wdt.c static int ftwdt010_wdt_probe(struct platform_device *pdev) · line 163
Quoted 3 lines
drivers/watchdog/ftwdt010_wdt.c +3
-0+ +/* Only enable and get frequency from EXTCLK if it's in use */ +if (gwdt->use_extclk) {
Does this use case still require pclk ?
Quoted 4 lines
drivers/watchdog/ftwdt010_wdt.c +4
-0+ gwdt->extclk =devm_clk_get (dev,"EXTCLK" ); +if (IS_ERR (gwdt->extclk)) { + ret =PTR_ERR (gwdt->extclk); + goto out_disable_pclk;
drivers/watchdog/ftwdt010_wdt.c static int ftwdt010_wdt_probe(struct platform_device *pdev) · line 177
Quoted 10 lines
drivers/watchdog/ftwdt010_wdt.c +10
-0+ } + 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() :-(.
Quoted 64 lines
drivers/watchdog/ftwdt010_wdt.c +29
-4+ } + 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),
PATCH v2 5/5 watchdog: ftwdt010: Add restart support
In reply to Linus WalleijThis enables the Faraday FTWDT010 to restart the system, if need be. Set the restart priority for the watchdog to 128.
---
ChangeLog v1->v2:
- Rebased, no changes.
--- drivers/watchdog/ftwdt010_wdt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/watchdog/ftwdt010_wdt.c +18 -0
@@ -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 ) {
Signature · 1 line
2.13.6
Guenter Roeck
maintainerPATCH v2 5/5 watchdog: ftwdt010: Add restart support
Quoted 5 lines · Linus Walleij
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 <[email protected]>
Quoted 50 lines
---
ChangeLogv1->v2:
- Rebased, no changes.--- drivers/watchdog/ftwdt010_wdt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)drivers/watchdog/ftwdt010_wdt.c +18
-0@@ -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 ) {
Guenter Roeck
maintainerPATCH v2 1/5 watchdog: gemini/ftwdt010: rename DT bindings
In reply to Linus WalleijQuoted 8 lines · Linus Walleij
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.orgAcked-by Rob Herring <[email protected]>Signed-off-by Linus Walleij <[email protected]>
Quoted 64 lines
---
ChangeLogv1->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%)Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt deleted +0
-17@@ -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>; -};Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt renamed from Documentation/devicetree/bindings/watchdog/cortina,gemin-watchdog.txt +8
-3@@ -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>; };