diff options
Diffstat (limited to 'drivers/watchdog/ath79_wdt.c')
-rw-r--r-- | drivers/watchdog/ath79_wdt.c | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c index 1f9371f49c40..898799074a13 100644 --- a/drivers/watchdog/ath79_wdt.c +++ b/drivers/watchdog/ath79_wdt.c @@ -23,6 +23,7 @@ #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/module.h> @@ -32,14 +33,16 @@ #include <linux/watchdog.h> #include <linux/clk.h> #include <linux/err.h> - -#include <asm/mach-ath79/ath79.h> -#include <asm/mach-ath79/ar71xx_regs.h> +#include <linux/of.h> +#include <linux/of_platform.h> #define DRIVER_NAME "ath79-wdt" #define WDT_TIMEOUT 15 /* seconds */ +#define WDOG_REG_CTRL 0x00 +#define WDOG_REG_TIMER 0x04 + #define WDOG_CTRL_LAST_RESET BIT(31) #define WDOG_CTRL_ACTION_MASK 3 #define WDOG_CTRL_ACTION_NONE 0 /* no action */ @@ -66,27 +69,38 @@ static struct clk *wdt_clk; static unsigned long wdt_freq; static int boot_status; static int max_timeout; +static void __iomem *wdt_base; + +static inline void ath79_wdt_wr(unsigned reg, u32 val) +{ + iowrite32(val, wdt_base + reg); +} + +static inline u32 ath79_wdt_rr(unsigned reg) +{ + return ioread32(wdt_base + reg); +} static inline void ath79_wdt_keepalive(void) { - ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout); + ath79_wdt_wr(WDOG_REG_TIMER, wdt_freq * timeout); /* flush write */ - ath79_reset_rr(AR71XX_RESET_REG_WDOG); + ath79_wdt_rr(WDOG_REG_TIMER); } static inline void ath79_wdt_enable(void) { ath79_wdt_keepalive(); - ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); + ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_FCR); /* flush write */ - ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); + ath79_wdt_rr(WDOG_REG_CTRL); } static inline void ath79_wdt_disable(void) { - ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); + ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_NONE); /* flush write */ - ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); + ath79_wdt_rr(WDOG_REG_CTRL); } static int ath79_wdt_set_timeout(int val) @@ -224,18 +238,34 @@ static struct miscdevice ath79_wdt_miscdev = { .fops = &ath79_wdt_fops, }; -static int __devinit ath79_wdt_probe(struct platform_device *pdev) +static int ath79_wdt_probe(struct platform_device *pdev) { + struct resource *res; u32 ctrl; int err; - wdt_clk = clk_get(&pdev->dev, "wdt"); + if (wdt_base) + return -EBUSY; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no memory resource found\n"); + return -EINVAL; + } + + wdt_base = devm_request_and_ioremap(&pdev->dev, res); + if (!wdt_base) { + dev_err(&pdev->dev, "unable to remap memory region\n"); + return -ENOMEM; + } + + wdt_clk = devm_clk_get(&pdev->dev, "wdt"); if (IS_ERR(wdt_clk)) return PTR_ERR(wdt_clk); err = clk_enable(wdt_clk); if (err) - goto err_clk_put; + return err; wdt_freq = clk_get_rate(wdt_clk); if (!wdt_freq) { @@ -251,7 +281,7 @@ static int __devinit ath79_wdt_probe(struct platform_device *pdev) max_timeout, timeout); } - ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); + ctrl = ath79_wdt_rr(WDOG_REG_CTRL); boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0; err = misc_register(&ath79_wdt_miscdev); @@ -265,16 +295,13 @@ static int __devinit ath79_wdt_probe(struct platform_device *pdev) err_clk_disable: clk_disable(wdt_clk); -err_clk_put: - clk_put(wdt_clk); return err; } -static int __devexit ath79_wdt_remove(struct platform_device *pdev) +static int ath79_wdt_remove(struct platform_device *pdev) { misc_deregister(&ath79_wdt_miscdev); clk_disable(wdt_clk); - clk_put(wdt_clk); return 0; } @@ -283,26 +310,26 @@ static void ath97_wdt_shutdown(struct platform_device *pdev) ath79_wdt_disable(); } +#ifdef CONFIG_OF +static const struct of_device_id ath79_wdt_match[] = { + { .compatible = "qca,ar7130-wdt" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ath79_wdt_match); +#endif + static struct platform_driver ath79_wdt_driver = { - .remove = __devexit_p(ath79_wdt_remove), + .probe = ath79_wdt_probe, + .remove = ath79_wdt_remove, .shutdown = ath97_wdt_shutdown, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ath79_wdt_match), }, }; -static int __init ath79_wdt_init(void) -{ - return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe); -} -module_init(ath79_wdt_init); - -static void __exit ath79_wdt_exit(void) -{ - platform_driver_unregister(&ath79_wdt_driver); -} -module_exit(ath79_wdt_exit); +module_platform_driver(ath79_wdt_driver); MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver"); MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org"); |