ARM: sunxi: New watchdog driver for Allwinner A10/A13
Subsystems (2)
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
--- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sunxi_wdt.c | 231 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 drivers/watchdog/sunxi_wdt.c
drivers/watchdog/Kconfig +10 -0
@@ -299,6 +299,16 @@ config ORION_WATCHDOG To compile this driver as a module, choose M here: the module will be called orion_wdt. +config SUNXI_WATCHDOG + tristate "Allwinner SoCs watchdog support" + depends on ARCH_SUNXI + select WATCHDOG_CORE + help + Say Y here to include support for the watchdog timer + in Allwinner SoCs. + To compile this driver as a module, choose M here: the + module will be called sunxi_wdt. + config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" depends on ARCH_U300
drivers/watchdog/Makefile +1 -0
@@ -47,6 +47,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o +obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
drivers/watchdog/sunxi_wdt.c new file +231 -0
231 lines not on this page · raw message
Signature · 1 line
1.8.2.3
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
Hi Carlo,
Quoted 4 lines · Carlo Caione
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>
It looks good to me.
Thanks for your work!
Maxime
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
In reply to Carlo CaioneQuoted 5 lines · Carlo Caione
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>---
[cut]
Ping
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
In reply to Carlo CaioneHi Wim,
Quoted 4 lines · Carlo Caione
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>
It would be great if we have this patch merged for 3.11, unless if you have additional comments of course.
Thanks,
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130623/3c23eff4/attachment.sig>
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
In reply to Carlo CaioneEm quinta-feira, 6 de junho de 2013 16h34min25s UTC-3, Carlo Caione escreveu:
Quoted 565 lines
This patch adds the driver for the watchdog found in the Allwinner A10 and
A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>---
drivers/watchdog/Kconfig | 10 ++drivers/watchdog/Makefile | 1 +drivers/watchdog/sunxi_wdt.c | 231 +++++++++++++++++++++++++++++++++++++++++++3 files changed, 242 insertions(+)create mode 100644 drivers/watchdog/sunxi_wdt.cdrivers/watchdog/Kconfig +0
-0index e89fc31..8ad2238 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
drivers/watchdog/Kconfig +10
-0@@ -299,6 +299,16 @@ config ORION_WATCHDOG To compile this driver as a module, choose M here: the module will be called orion_wdt. +config SUNXI_WATCHDOG + tristate "Allwinner SoCs watchdog support" + depends on ARCH_SUNXI + select WATCHDOG_CORE + help + Say Y here to include support for the watchdog timer + in Allwinner SoCs. + To compile this driver as a module, choose M here: the + module will be called sunxi_wdt. + config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" depends on ARCH_U300drivers/watchdog/Makefile +0
-0index a300b94..5012d5f 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
drivers/watchdog/Makefile +1
-0@@ -47,6 +47,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o +obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.odrivers/watchdog/sunxi_wdt.c +0
-0new file mode 100644
index 0000000..69d4d44
---
/dev/null+++
b/drivers/watchdog/sunxi_wdt.cdrivers/watchdog/sunxi_wdt.c +231
-0@@ -0,0 +1,231 @@ +/* +* sunxi Watchdog Driver +* +* Copyright (c) 2013 Carlo Caione +* 2012 Henrik Nordstrom +* +* 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. +* +* Based on xen_wdt.c +* (c) Copyright 2010 Novell, Inc. +*/ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/watchdog.h> + +#define WDT_MAX_TIMEOUT 16 +#define WDT_MIN_TIMEOUT 1 +#define WDT_MODE_TIMEOUT (n) ((n) << 3) +#define WDT_TIMEOUT_MASK WDT_MODE_TIMEOUT(0x0F) + +#define WDT_CTRL 0x00 +#define WDT_CTRL_RELOAD ((1 << 0) | (0x0a57 << 1)) + +#define WDT_MODE 0x04 +#define WDT_MODE_EN (1 << 0) +#define WDT_MODE_RST_EN (1 << 1) + +#define DRV_NAME "sunxi-wdt" +#define DRV_VERSION "1.0" + +static bool nowayout =WATCHDOG_NOWAYOUT ; +static int heartbeat =WDT_MAX_TIMEOUT ; + +struct sunxi_wdt_dev { +struct watchdog_device wdt_dev; +void __iomem *wdt_base; +}; + +/* +* wdt_timeout_map maps the watchdog timer interval value in seconds to +* the value of the register WDT_MODE bit 3:6 +* +* [timeout seconds] = register value +* +*/ + +static const int wdt_timeout_map[] = { + [1 ] =0b0001 ,/* 1s */ + [2 ] =0b0010 ,/* 2s */ + [3 ] =0b0011 ,/* 3s */ + [4 ] =0b0100 ,/* 4s */ + [5 ] =0b0101 ,/* 5s */ + [6 ] =0b0110 ,/* 6s */ + [8 ] =0b0111 ,/* 8s */ + [10 ] =0b1000 ,/* 10s */ + [12 ] =0b1001 ,/* 12s */ + [14 ] =0b1010 ,/* 14s */ + [16 ] =0b1011 ,/* 16s */ +}; + +static int sunxi_wdt_ping (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (WDT_CTRL_RELOAD , wdt_base +WDT_CTRL ); + +return 0 ; +} + +static int sunxi_wdt_set_timeout (struct watchdog_device *wdt_dev, +unsigned int timeout) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +u32 reg; + +if (timeout >WDT_MAX_TIMEOUT ) +return -EINVAL ; + +if (wdt_timeout_map[timeout] ==0 ) + timeout++; + + sunxi_wdt->wdt_dev.timeout = timeout; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg &= ~WDT_TIMEOUT_MASK ; + reg |=WDT_MODE_TIMEOUT (wdt_timeout_map[timeout]); +iowrite32 (reg, wdt_base +WDT_MODE ); + +sunxi_wdt_ping (wdt_dev); + +return 0 ; +} + +static int sunxi_wdt_stop (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (0 , wdt_base +WDT_MODE ); + +return 0 ; +} + +static int sunxi_wdt_start (struct watchdog_device *wdt_dev) +{ +u32 reg; +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +int ret; + + ret =sunxi_wdt_set_timeout (&sunxi_wdt->wdt_dev, + sunxi_wdt->wdt_dev.timeout); +if (ret <0 ) +return ret; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg |= (WDT_MODE_RST_EN |WDT_MODE_EN ); +iowrite32 (reg, wdt_base +WDT_MODE ); + +return 0 ; +} + +static const struct watchdog_info sunxi_wdt_info = { + .identity =DRV_NAME , + .options =WDIOF_SETTIMEOUT | +WDIOF_KEEPALIVEPING | +WDIOF_MAGICCLOSE , +}; + +static const struct watchdog_ops sunxi_wdt_ops = { + .owner =THIS_MODULE , + .start = sunxi_wdt_start, + .stop = sunxi_wdt_stop, + .ping = sunxi_wdt_ping, + .set_timeout = sunxi_wdt_set_timeout, +}; + +static int __init sunxi_wdt_probe (struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt; +struct resource *res; +int err; + + sunxi_wdt =devm_kzalloc (&pdev->dev,sizeof (*sunxi_wdt),GFP_KERNEL ); +if (!sunxi_wdt) +return -EINVAL ; + +platform_set_drvdata (pdev, sunxi_wdt); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + sunxi_wdt->wdt_base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (sunxi_wdt->wdt_base)) +return PTR_ERR (sunxi_wdt->wdt_base); + + sunxi_wdt->wdt_dev.info = &sunxi_wdt_info; + sunxi_wdt->wdt_dev.ops = &sunxi_wdt_ops; + sunxi_wdt->wdt_dev.timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.max_timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.min_timeout =WDT_MIN_TIMEOUT ; + sunxi_wdt->wdt_dev.parent = &pdev->dev; + +watchdog_init_timeout (&sunxi_wdt->wdt_dev, heartbeat, &pdev->dev); +watchdog_set_nowayout (&sunxi_wdt->wdt_dev, nowayout); + +watchdog_set_drvdata (&sunxi_wdt->wdt_dev, sunxi_wdt); + + err =watchdog_register_device (&sunxi_wdt->wdt_dev); +if (unlikely (err)) +return err; + +dev_info (&pdev->dev,"Watchdog enabled (heartbeat=%d sec, nowayout=%d)" , + sunxi_wdt->wdt_dev.timeout, nowayout); + +return 0 ; +} + +static int __exit sunxi_wdt_remove(struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt =platform_get_drvdata (pdev); + +watchdog_unregister_device (&sunxi_wdt->wdt_dev); +watchdog_set_drvdata (&sunxi_wdt->wdt_dev,NULL ); + +return 0 ; +} + +static const struct of_device_id sunxi_wdt_dt_ids[] = { + { .compatible ="allwinner,sun4i-wdt" }, + {/* sentinel */ } +}; +MODULE_DEVICE_TABLE (of, sunxi_wdt_dt_ids); + +static struct platform_driver sunxi_wdt_driver = { + .probe = sunxi_wdt_probe, + .remove = sunxi_wdt_remove, + .driver = { + .owner =THIS_MODULE , + .name =DRV_NAME , + .of_match_table =of_match_ptr (sunxi_wdt_dt_ids) + }, +}; + +module_platform_driver (sunxi_wdt_driver); + +module_param (heartbeat, int,0 ); +MODULE_PARM_DESC (heartbeat,"Watchdog heartbeat in seconds" ); + +module_param (nowayout, bool,0 ); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Carlo Caione <[email protected]>" ); +MODULE_AUTHOR ("Henrik Nordstrom <[email protected]>" ); +MODULE_DESCRIPTION ("sunxi WatchDog Timer Driver" ); +MODULE_VERSION (DRV_VERSION );Signature · 3 lines
-- 1.8.2.3
Hi Carlo,
It is not possible to enable this driver because there is no 'ARCH_SUNXI' in default .config. What you intended to use, 'ARCH_SUNXI' or 'ARCH_SUN4I'? RTC driver presents the same issue.
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
Quoted 5 lines · viniciusfre at gmail.com
Hi Carlo,
It is not possible to enable this driver because there is no '
ARCH_SUNXI' in default .config. What you intended to use, 'ARCH_SUNXI' or 'ARCH_SUN4I'? RTC driver presents the same issue.
This driver is intended for the mainline Linux Kernel, where ARCH_SUN4i doesn't exist, and ARCH_SUNXI actually does.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130706/cc645530/attachment.sig>
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
In reply to Carlo CaioneWim,
Quoted 4 lines · Carlo Caione
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>
This patch has been sent over a month ago now, without any review or comments from your part.
Do you intend to merge it at some point?
Thanks,
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130706/495e7dc7/attachment.sig>
Hi Maxime,
Quoted 9 lines
Quoted 4 lines
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>This patch has been sent over a month ago now, without any review or comments from your part.
Do you intend to merge it at some point?
Correct, Review will happen shortly and then we will see if we can merge it.
Kind regards,
Wim.
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
In reply to Carlo CaioneEm quinta-feira, 6 de junho de 2013 16h34min25s UTC-3, Carlo Caione escreveu:
Quoted 565 lines
This patch adds the driver for the watchdog found in the Allwinner A10 and
A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>---
drivers/watchdog/Kconfig | 10 ++drivers/watchdog/Makefile | 1 +drivers/watchdog/sunxi_wdt.c | 231 +++++++++++++++++++++++++++++++++++++++++++3 files changed, 242 insertions(+)create mode 100644 drivers/watchdog/sunxi_wdt.cdrivers/watchdog/Kconfig +0
-0index e89fc31..8ad2238 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
drivers/watchdog/Kconfig +10
-0@@ -299,6 +299,16 @@ config ORION_WATCHDOG To compile this driver as a module, choose M here: the module will be called orion_wdt. +config SUNXI_WATCHDOG + tristate "Allwinner SoCs watchdog support" + depends on ARCH_SUNXI + select WATCHDOG_CORE + help + Say Y here to include support for the watchdog timer + in Allwinner SoCs. + To compile this driver as a module, choose M here: the + module will be called sunxi_wdt. + config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" depends on ARCH_U300drivers/watchdog/Makefile +0
-0index a300b94..5012d5f 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
drivers/watchdog/Makefile +1
-0@@ -47,6 +47,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o +obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.odrivers/watchdog/sunxi_wdt.c +0
-0new file mode 100644
index 0000000..69d4d44
---
/dev/null+++
b/drivers/watchdog/sunxi_wdt.cdrivers/watchdog/sunxi_wdt.c +231
-0@@ -0,0 +1,231 @@ +/* +* sunxi Watchdog Driver +* +* Copyright (c) 2013 Carlo Caione +* 2012 Henrik Nordstrom +* +* 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. +* +* Based on xen_wdt.c +* (c) Copyright 2010 Novell, Inc. +*/ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/watchdog.h> + +#define WDT_MAX_TIMEOUT 16 +#define WDT_MIN_TIMEOUT 1 +#define WDT_MODE_TIMEOUT (n) ((n) << 3) +#define WDT_TIMEOUT_MASK WDT_MODE_TIMEOUT(0x0F) + +#define WDT_CTRL 0x00 +#define WDT_CTRL_RELOAD ((1 << 0) | (0x0a57 << 1)) + +#define WDT_MODE 0x04 +#define WDT_MODE_EN (1 << 0) +#define WDT_MODE_RST_EN (1 << 1) + +#define DRV_NAME "sunxi-wdt" +#define DRV_VERSION "1.0" + +static bool nowayout =WATCHDOG_NOWAYOUT ; +static int heartbeat =WDT_MAX_TIMEOUT ; + +struct sunxi_wdt_dev { +struct watchdog_device wdt_dev; +void __iomem *wdt_base; +}; + +/* +* wdt_timeout_map maps the watchdog timer interval value in seconds to +* the value of the register WDT_MODE bit 3:6 +* +* [timeout seconds] = register value +* +*/ + +static const int wdt_timeout_map[] = { + [1 ] =0b0001 ,/* 1s */ + [2 ] =0b0010 ,/* 2s */ + [3 ] =0b0011 ,/* 3s */ + [4 ] =0b0100 ,/* 4s */ + [5 ] =0b0101 ,/* 5s */ + [6 ] =0b0110 ,/* 6s */ + [8 ] =0b0111 ,/* 8s */ + [10 ] =0b1000 ,/* 10s */ + [12 ] =0b1001 ,/* 12s */ + [14 ] =0b1010 ,/* 14s */ + [16 ] =0b1011 ,/* 16s */ +}; + +static int sunxi_wdt_ping (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (WDT_CTRL_RELOAD , wdt_base +WDT_CTRL ); + +return 0 ; +} + +static int sunxi_wdt_set_timeout (struct watchdog_device *wdt_dev, +unsigned int timeout) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +u32 reg; + +if (timeout >WDT_MAX_TIMEOUT ) +return -EINVAL ; + +if (wdt_timeout_map[timeout] ==0 ) + timeout++; + + sunxi_wdt->wdt_dev.timeout = timeout; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg &= ~WDT_TIMEOUT_MASK ; + reg |=WDT_MODE_TIMEOUT (wdt_timeout_map[timeout]); +iowrite32 (reg, wdt_base +WDT_MODE ); + +sunxi_wdt_ping (wdt_dev); + +return 0 ; +} + +static int sunxi_wdt_stop (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (0 , wdt_base +WDT_MODE ); + +return 0 ; +} + +static int sunxi_wdt_start (struct watchdog_device *wdt_dev) +{ +u32 reg; +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +int ret; + + ret =sunxi_wdt_set_timeout (&sunxi_wdt->wdt_dev, + sunxi_wdt->wdt_dev.timeout); +if (ret <0 ) +return ret; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg |= (WDT_MODE_RST_EN |WDT_MODE_EN ); +iowrite32 (reg, wdt_base +WDT_MODE ); + +return 0 ; +} + +static const struct watchdog_info sunxi_wdt_info = { + .identity =DRV_NAME , + .options =WDIOF_SETTIMEOUT | +WDIOF_KEEPALIVEPING | +WDIOF_MAGICCLOSE , +}; + +static const struct watchdog_ops sunxi_wdt_ops = { + .owner =THIS_MODULE , + .start = sunxi_wdt_start, + .stop = sunxi_wdt_stop, + .ping = sunxi_wdt_ping, + .set_timeout = sunxi_wdt_set_timeout, +}; + +static int __init sunxi_wdt_probe (struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt; +struct resource *res; +int err; + + sunxi_wdt =devm_kzalloc (&pdev->dev,sizeof (*sunxi_wdt),GFP_KERNEL ); +if (!sunxi_wdt) +return -EINVAL ; + +platform_set_drvdata (pdev, sunxi_wdt); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + sunxi_wdt->wdt_base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (sunxi_wdt->wdt_base)) +return PTR_ERR (sunxi_wdt->wdt_base); + + sunxi_wdt->wdt_dev.info = &sunxi_wdt_info; + sunxi_wdt->wdt_dev.ops = &sunxi_wdt_ops; + sunxi_wdt->wdt_dev.timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.max_timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.min_timeout =WDT_MIN_TIMEOUT ; + sunxi_wdt->wdt_dev.parent = &pdev->dev; + +watchdog_init_timeout (&sunxi_wdt->wdt_dev, heartbeat, &pdev->dev); +watchdog_set_nowayout (&sunxi_wdt->wdt_dev, nowayout); + +watchdog_set_drvdata (&sunxi_wdt->wdt_dev, sunxi_wdt); + + err =watchdog_register_device (&sunxi_wdt->wdt_dev); +if (unlikely (err)) +return err; + +dev_info (&pdev->dev,"Watchdog enabled (heartbeat=%d sec, nowayout=%d)" , + sunxi_wdt->wdt_dev.timeout, nowayout); + +return 0 ; +} + +static int __exit sunxi_wdt_remove(struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt =platform_get_drvdata (pdev); + +watchdog_unregister_device (&sunxi_wdt->wdt_dev); +watchdog_set_drvdata (&sunxi_wdt->wdt_dev,NULL ); + +return 0 ; +} + +static const struct of_device_id sunxi_wdt_dt_ids[] = { + { .compatible ="allwinner,sun4i-wdt" }, + {/* sentinel */ } +}; +MODULE_DEVICE_TABLE (of, sunxi_wdt_dt_ids); + +static struct platform_driver sunxi_wdt_driver = { + .probe = sunxi_wdt_probe, + .remove = sunxi_wdt_remove, + .driver = { + .owner =THIS_MODULE , + .name =DRV_NAME , + .of_match_table =of_match_ptr (sunxi_wdt_dt_ids) + }, +}; + +module_platform_driver (sunxi_wdt_driver); + +module_param (heartbeat, int,0 ); +MODULE_PARM_DESC (heartbeat,"Watchdog heartbeat in seconds" ); + +module_param (nowayout, bool,0 ); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Carlo Caione <[email protected]>" ); +MODULE_AUTHOR ("Henrik Nordstrom <[email protected]>" ); +MODULE_DESCRIPTION ("sunxi WatchDog Timer Driver" ); +MODULE_VERSION (DRV_VERSION );Signature · 3 lines
-- 1.8.2.3
Ok, sorry about that. Anyway, this driver can be not used in linux-sunxi?
PATCH v5 1/1 ARM: sunxi: New watchdog driver for Allwinner A10/A13
Quoted 2 lines · viniciusfre at gmail.com
Ok, sorry about that. Anyway, this driver can be not used in linux-sunxi?
It's already in use in linux-sunxi.
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130706/63fd904c/attachment.sig>
Hi Carlo,
Quoted 85 lines
This patch adds the driver for the watchdog found in the Allwinner A10 and A13 SoCs. It has DT-support and uses the new watchdog framework.
Signed-off-by Carlo Caione <[email protected]>--- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sunxi_wdt.c | 231 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 drivers/watchdog/sunxi_wdt.cdrivers/watchdog/Kconfig +10
-0@@ -299,6 +299,16 @@ config ORION_WATCHDOG To compile this driver as a module, choose M here: the module will be called orion_wdt. +config SUNXI_WATCHDOG + tristate "Allwinner SoCs watchdog support" + depends on ARCH_SUNXI + select WATCHDOG_CORE + help + Say Y here to include support for the watchdog timer + in Allwinner SoCs. + To compile this driver as a module, choose M here: the + module will be called sunxi_wdt. + config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" depends on ARCH_U300drivers/watchdog/Makefile +1
-0@@ -47,6 +47,7 @@ obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o +obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.odrivers/watchdog/sunxi_wdt.c new file +35
-0@@ -0,0 +1,231 @@ +/* +* sunxi Watchdog Driver +* +* Copyright (c) 2013 Carlo Caione +* 2012 Henrik Nordstrom +* +* 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. +* +* Based on xen_wdt.c +* (c) Copyright 2010 Novell, Inc. +*/ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <linux/watchdog.h> + +#define WDT_MAX_TIMEOUT 16 +#define WDT_MIN_TIMEOUT 1 +#define WDT_MODE_TIMEOUT (n) ((n) << 3) +#define WDT_TIMEOUT_MASK WDT_MODE_TIMEOUT(0x0F) + +#define WDT_CTRL 0x00 +#define WDT_CTRL_RELOAD ((1 << 0) | (0x0a57 << 1))
drivers/watchdog/sunxi_wdt.c line 45
Quoted 10 lines
drivers/watchdog/sunxi_wdt.c new file +10
-0+ +#define WDT_MODE 0x04 +#define WDT_MODE_EN (1 << 0) +#define WDT_MODE_RST_EN (1 << 1) + +#define DRV_NAME "sunxi-wdt" +#define DRV_VERSION "1.0" + +static bool nowayout =WATCHDOG_NOWAYOUT ; +static int heartbeat =WDT_MAX_TIMEOUT ;
heartbeat should be unsigned int.
I also prefer this to be called timeout. (heartbeat is what we use towards the watchdog, timeout is what we use for user-space. In this case heartbeat will be equal to timeout).
Quoted 125 lines
drivers/watchdog/sunxi_wdt.c new file +125
-0+ +struct sunxi_wdt_dev { +struct watchdog_device wdt_dev; +void __iomem *wdt_base; +}; + +/* +* wdt_timeout_map maps the watchdog timer interval value in seconds to +* the value of the register WDT_MODE bit 3:6 +* +* [timeout seconds] = register value +* +*/ + +static const int wdt_timeout_map[] = { + [1 ] =0b0001 ,/* 1s */ + [2 ] =0b0010 ,/* 2s */ + [3 ] =0b0011 ,/* 3s */ + [4 ] =0b0100 ,/* 4s */ + [5 ] =0b0101 ,/* 5s */ + [6 ] =0b0110 ,/* 6s */ + [8 ] =0b0111 ,/* 8s */ + [10 ] =0b1000 ,/* 10s */ + [12 ] =0b1001 ,/* 12s */ + [14 ] =0b1010 ,/* 14s */ + [16 ] =0b1011 ,/* 16s */ +}; + +static int sunxi_wdt_ping (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (WDT_CTRL_RELOAD , wdt_base +WDT_CTRL ); + +return 0 ; +} + +static int sunxi_wdt_set_timeout (struct watchdog_device *wdt_dev, +unsigned int timeout) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +u32 reg; + +if (timeout >WDT_MAX_TIMEOUT ) +return -EINVAL ; + +if (wdt_timeout_map[timeout] ==0 ) + timeout++; + + sunxi_wdt->wdt_dev.timeout = timeout; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg &= ~WDT_TIMEOUT_MASK ; + reg |=WDT_MODE_TIMEOUT (wdt_timeout_map[timeout]); +iowrite32 (reg, wdt_base +WDT_MODE ); + +sunxi_wdt_ping (wdt_dev); + +return 0 ; +} + +static int sunxi_wdt_stop (struct watchdog_device *wdt_dev) +{ +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; + +iowrite32 (0 , wdt_base +WDT_MODE ); + +return 0 ; +} + +static int sunxi_wdt_start (struct watchdog_device *wdt_dev) +{ +u32 reg; +struct sunxi_wdt_dev *sunxi_wdt =watchdog_get_drvdata (wdt_dev); +void __iomem *wdt_base = sunxi_wdt->wdt_base; +int ret; + + ret =sunxi_wdt_set_timeout (&sunxi_wdt->wdt_dev, + sunxi_wdt->wdt_dev.timeout); +if (ret <0 ) +return ret; + + reg =ioread32 (wdt_base +WDT_MODE ); + reg |= (WDT_MODE_RST_EN |WDT_MODE_EN ); +iowrite32 (reg, wdt_base +WDT_MODE ); + +return 0 ; +} + +static const struct watchdog_info sunxi_wdt_info = { + .identity =DRV_NAME , + .options =WDIOF_SETTIMEOUT | +WDIOF_KEEPALIVEPING | +WDIOF_MAGICCLOSE , +}; + +static const struct watchdog_ops sunxi_wdt_ops = { + .owner =THIS_MODULE , + .start = sunxi_wdt_start, + .stop = sunxi_wdt_stop, + .ping = sunxi_wdt_ping, + .set_timeout = sunxi_wdt_set_timeout, +}; + +static int __init sunxi_wdt_probe (struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt; +struct resource *res; +int err; + + sunxi_wdt =devm_kzalloc (&pdev->dev,sizeof (*sunxi_wdt),GFP_KERNEL ); +if (!sunxi_wdt) +return -EINVAL ; + +platform_set_drvdata (pdev, sunxi_wdt); + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + sunxi_wdt->wdt_base =devm_ioremap_resource (&pdev->dev, res); +if (IS_ERR (sunxi_wdt->wdt_base)) +return PTR_ERR (sunxi_wdt->wdt_base); + + sunxi_wdt->wdt_dev.info = &sunxi_wdt_info;
drivers/watchdog/sunxi_wdt.c line 180
Quoted 10 lines
drivers/watchdog/sunxi_wdt.c new file +10
-0+ sunxi_wdt->wdt_dev.ops = &sunxi_wdt_ops; + sunxi_wdt->wdt_dev.timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.max_timeout =WDT_MAX_TIMEOUT ; + sunxi_wdt->wdt_dev.min_timeout =WDT_MIN_TIMEOUT ; + sunxi_wdt->wdt_dev.parent = &pdev->dev; + +watchdog_init_timeout (&sunxi_wdt->wdt_dev, heartbeat, &pdev->dev); +watchdog_set_nowayout (&sunxi_wdt->wdt_dev, nowayout); + +watchdog_set_drvdata (&sunxi_wdt->wdt_dev, sunxi_wdt);
Can the watchdog be running at startup before the driver loads? If so you should make sure that you stop the watchdog.
Quoted 19 lines
drivers/watchdog/sunxi_wdt.c new file +19
-0+ err =watchdog_register_device (&sunxi_wdt->wdt_dev); +if (unlikely (err)) +return err; + +dev_info (&pdev->dev,"Watchdog enabled (heartbeat=%d sec, nowayout=%d)" , + sunxi_wdt->wdt_dev.timeout, nowayout); + +return 0 ; +} + +static int __exit sunxi_wdt_remove(struct platform_device *pdev) +{ +struct sunxi_wdt_dev *sunxi_wdt =platform_get_drvdata (pdev); + +watchdog_unregister_device (&sunxi_wdt->wdt_dev); +watchdog_set_drvdata (&sunxi_wdt->wdt_dev,NULL ); + +return 0 ; +}
drivers/watchdog/sunxi_wdt.c line 210
Quoted 10 lines
drivers/watchdog/sunxi_wdt.c new file +10
-0+ +static const struct of_device_id sunxi_wdt_dt_ids[] = { + { .compatible ="allwinner,sun4i-wdt" }, + {/* sentinel */ } +}; +MODULE_DEVICE_TABLE (of, sunxi_wdt_dt_ids); + +static struct platform_driver sunxi_wdt_driver = { + .probe = sunxi_wdt_probe, + .remove = sunxi_wdt_remove,
May be interesting to add the shutdown method also... (so that the watchog doesn't get fired when, you are allready shutting down).
drivers/watchdog/sunxi_wdt.c line 221
Quoted 11 lines
drivers/watchdog/sunxi_wdt.c new file +11
-0+ .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + .of_match_table =of_match_ptr (sunxi_wdt_dt_ids) + }, +}; + +module_platform_driver (sunxi_wdt_driver); + +module_param (heartbeat, int,0 ); +MODULE_PARM_DESC (heartbeat,"Watchdog heartbeat in seconds" );
Unsigned int and timeout is prefered name here.
drivers/watchdog/sunxi_wdt.c line 231
Quoted 10 lines
drivers/watchdog/sunxi_wdt.c new file +10
-0+ +module_param (nowayout, bool,0 ); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Carlo Caione <[email protected]>" ); +MODULE_AUTHOR ("Henrik Nordstrom <[email protected]>" ); +MODULE_DESCRIPTION ("sunxi WatchDog Timer Driver" ); +MODULE_VERSION (DRV_VERSION );
For the rest: looks ok.
Kind regards,
Wim.