Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Watchdog driver for Atmel AT91SAM9x processors.
0004  *
0005  * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr
0006  *
0007  */
0008 
0009 /*
0010  * The Watchdog Timer Mode Register can be only written to once. If the
0011  * timeout need to be set from Linux, be sure that the bootstrap or the
0012  * bootloader doesn't write to this register.
0013  */
0014 
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016 
0017 #include <linux/clk.h>
0018 #include <linux/errno.h>
0019 #include <linux/init.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/io.h>
0022 #include <linux/kernel.h>
0023 #include <linux/module.h>
0024 #include <linux/moduleparam.h>
0025 #include <linux/platform_device.h>
0026 #include <linux/reboot.h>
0027 #include <linux/types.h>
0028 #include <linux/watchdog.h>
0029 #include <linux/jiffies.h>
0030 #include <linux/timer.h>
0031 #include <linux/bitops.h>
0032 #include <linux/uaccess.h>
0033 #include <linux/of.h>
0034 #include <linux/of_irq.h>
0035 
0036 #include "at91sam9_wdt.h"
0037 
0038 #define DRV_NAME "AT91SAM9 Watchdog"
0039 
0040 #define wdt_read(wdt, field) \
0041     readl_relaxed((wdt)->base + (field))
0042 #define wdt_write(wtd, field, val) \
0043     writel_relaxed((val), (wdt)->base + (field))
0044 
0045 /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz,
0046  * use this to convert a watchdog
0047  * value from/to milliseconds.
0048  */
0049 #define ticks_to_hz_rounddown(t)    ((((t) + 1) * HZ) >> 8)
0050 #define ticks_to_hz_roundup(t)      (((((t) + 1) * HZ) + 255) >> 8)
0051 #define ticks_to_secs(t)        (((t) + 1) >> 8)
0052 #define secs_to_ticks(s)        ((s) ? (((s) << 8) - 1) : 0)
0053 
0054 #define WDT_MR_RESET    0x3FFF2FFF
0055 
0056 /* Watchdog max counter value in ticks */
0057 #define WDT_COUNTER_MAX_TICKS   0xFFF
0058 
0059 /* Watchdog max delta/value in secs */
0060 #define WDT_COUNTER_MAX_SECS    ticks_to_secs(WDT_COUNTER_MAX_TICKS)
0061 
0062 /* Hardware timeout in seconds */
0063 #define WDT_HW_TIMEOUT 2
0064 
0065 /* Timer heartbeat (500ms) */
0066 #define WDT_TIMEOUT (HZ/2)
0067 
0068 /* User land timeout */
0069 #define WDT_HEARTBEAT 15
0070 static int heartbeat;
0071 module_param(heartbeat, int, 0);
0072 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
0073     "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
0074 
0075 static bool nowayout = WATCHDOG_NOWAYOUT;
0076 module_param(nowayout, bool, 0);
0077 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
0078     "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0079 
0080 #define to_wdt(wdd) container_of(wdd, struct at91wdt, wdd)
0081 struct at91wdt {
0082     struct watchdog_device wdd;
0083     void __iomem *base;
0084     unsigned long next_heartbeat;   /* the next_heartbeat for the timer */
0085     struct timer_list timer;    /* The timer that pings the watchdog */
0086     u32 mr;
0087     u32 mr_mask;
0088     unsigned long heartbeat;    /* WDT heartbeat in jiffies */
0089     bool nowayout;
0090     unsigned int irq;
0091     struct clk *sclk;
0092 };
0093 
0094 /* ......................................................................... */
0095 
0096 static irqreturn_t wdt_interrupt(int irq, void *dev_id)
0097 {
0098     struct at91wdt *wdt = (struct at91wdt *)dev_id;
0099 
0100     if (wdt_read(wdt, AT91_WDT_SR)) {
0101         pr_crit("at91sam9 WDT software reset\n");
0102         emergency_restart();
0103         pr_crit("Reboot didn't ?????\n");
0104     }
0105 
0106     return IRQ_HANDLED;
0107 }
0108 
0109 /*
0110  * Reload the watchdog timer.  (ie, pat the watchdog)
0111  */
0112 static inline void at91_wdt_reset(struct at91wdt *wdt)
0113 {
0114     wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
0115 }
0116 
0117 /*
0118  * Timer tick
0119  */
0120 static void at91_ping(struct timer_list *t)
0121 {
0122     struct at91wdt *wdt = from_timer(wdt, t, timer);
0123     if (time_before(jiffies, wdt->next_heartbeat) ||
0124         !watchdog_active(&wdt->wdd)) {
0125         at91_wdt_reset(wdt);
0126         mod_timer(&wdt->timer, jiffies + wdt->heartbeat);
0127     } else {
0128         pr_crit("I will reset your machine !\n");
0129     }
0130 }
0131 
0132 static int at91_wdt_start(struct watchdog_device *wdd)
0133 {
0134     struct at91wdt *wdt = to_wdt(wdd);
0135     /* calculate when the next userspace timeout will be */
0136     wdt->next_heartbeat = jiffies + wdd->timeout * HZ;
0137     return 0;
0138 }
0139 
0140 static int at91_wdt_stop(struct watchdog_device *wdd)
0141 {
0142     /* The watchdog timer hardware can not be stopped... */
0143     return 0;
0144 }
0145 
0146 static int at91_wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout)
0147 {
0148     wdd->timeout = new_timeout;
0149     return at91_wdt_start(wdd);
0150 }
0151 
0152 static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt)
0153 {
0154     u32 tmp;
0155     u32 delta;
0156     u32 value;
0157     int err;
0158     u32 mask = wdt->mr_mask;
0159     unsigned long min_heartbeat = 1;
0160     unsigned long max_heartbeat;
0161     struct device *dev = &pdev->dev;
0162 
0163     tmp = wdt_read(wdt, AT91_WDT_MR);
0164     if ((tmp & mask) != (wdt->mr & mask)) {
0165         if (tmp == WDT_MR_RESET) {
0166             wdt_write(wdt, AT91_WDT_MR, wdt->mr);
0167             tmp = wdt_read(wdt, AT91_WDT_MR);
0168         }
0169     }
0170 
0171     if (tmp & AT91_WDT_WDDIS) {
0172         if (wdt->mr & AT91_WDT_WDDIS)
0173             return 0;
0174         dev_err(dev, "watchdog is disabled\n");
0175         return -EINVAL;
0176     }
0177 
0178     value = tmp & AT91_WDT_WDV;
0179     delta = (tmp & AT91_WDT_WDD) >> 16;
0180 
0181     if (delta < value)
0182         min_heartbeat = ticks_to_hz_roundup(value - delta);
0183 
0184     max_heartbeat = ticks_to_hz_rounddown(value);
0185     if (!max_heartbeat) {
0186         dev_err(dev,
0187             "heartbeat is too small for the system to handle it correctly\n");
0188         return -EINVAL;
0189     }
0190 
0191     /*
0192      * Try to reset the watchdog counter 4 or 2 times more often than
0193      * actually requested, to avoid spurious watchdog reset.
0194      * If this is not possible because of the min_heartbeat value, reset
0195      * it at the min_heartbeat period.
0196      */
0197     if ((max_heartbeat / 4) >= min_heartbeat)
0198         wdt->heartbeat = max_heartbeat / 4;
0199     else if ((max_heartbeat / 2) >= min_heartbeat)
0200         wdt->heartbeat = max_heartbeat / 2;
0201     else
0202         wdt->heartbeat = min_heartbeat;
0203 
0204     if (max_heartbeat < min_heartbeat + 4)
0205         dev_warn(dev,
0206              "min heartbeat and max heartbeat might be too close for the system to handle it correctly\n");
0207 
0208     if ((tmp & AT91_WDT_WDFIEN) && wdt->irq) {
0209         err = request_irq(wdt->irq, wdt_interrupt,
0210                   IRQF_SHARED | IRQF_IRQPOLL |
0211                   IRQF_NO_SUSPEND,
0212                   pdev->name, wdt);
0213         if (err)
0214             return err;
0215     }
0216 
0217     if ((tmp & wdt->mr_mask) != (wdt->mr & wdt->mr_mask))
0218         dev_warn(dev,
0219              "watchdog already configured differently (mr = %x expecting %x)\n",
0220              tmp & wdt->mr_mask, wdt->mr & wdt->mr_mask);
0221 
0222     timer_setup(&wdt->timer, at91_ping, 0);
0223 
0224     /*
0225      * Use min_heartbeat the first time to avoid spurious watchdog reset:
0226      * we don't know for how long the watchdog counter is running, and
0227      *  - resetting it right now might trigger a watchdog fault reset
0228      *  - waiting for heartbeat time might lead to a watchdog timeout
0229      *    reset
0230      */
0231     mod_timer(&wdt->timer, jiffies + min_heartbeat);
0232 
0233     /* Try to set timeout from device tree first */
0234     if (watchdog_init_timeout(&wdt->wdd, 0, dev))
0235         watchdog_init_timeout(&wdt->wdd, heartbeat, dev);
0236     watchdog_set_nowayout(&wdt->wdd, wdt->nowayout);
0237     err = watchdog_register_device(&wdt->wdd);
0238     if (err)
0239         goto out_stop_timer;
0240 
0241     wdt->next_heartbeat = jiffies + wdt->wdd.timeout * HZ;
0242 
0243     return 0;
0244 
0245 out_stop_timer:
0246     del_timer(&wdt->timer);
0247     return err;
0248 }
0249 
0250 /* ......................................................................... */
0251 
0252 static const struct watchdog_info at91_wdt_info = {
0253     .identity   = DRV_NAME,
0254     .options    = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
0255                         WDIOF_MAGICCLOSE,
0256 };
0257 
0258 static const struct watchdog_ops at91_wdt_ops = {
0259     .owner =    THIS_MODULE,
0260     .start =    at91_wdt_start,
0261     .stop =     at91_wdt_stop,
0262     .set_timeout =  at91_wdt_set_timeout,
0263 };
0264 
0265 #if defined(CONFIG_OF)
0266 static int of_at91wdt_init(struct device_node *np, struct at91wdt *wdt)
0267 {
0268     u32 min = 0;
0269     u32 max = WDT_COUNTER_MAX_SECS;
0270     const char *tmp;
0271 
0272     /* Get the interrupts property */
0273     wdt->irq = irq_of_parse_and_map(np, 0);
0274     if (!wdt->irq)
0275         dev_warn(wdt->wdd.parent, "failed to get IRQ from DT\n");
0276 
0277     if (!of_property_read_u32_index(np, "atmel,max-heartbeat-sec", 0,
0278                     &max)) {
0279         if (!max || max > WDT_COUNTER_MAX_SECS)
0280             max = WDT_COUNTER_MAX_SECS;
0281 
0282         if (!of_property_read_u32_index(np, "atmel,min-heartbeat-sec",
0283                         0, &min)) {
0284             if (min >= max)
0285                 min = max - 1;
0286         }
0287     }
0288 
0289     min = secs_to_ticks(min);
0290     max = secs_to_ticks(max);
0291 
0292     wdt->mr_mask = 0x3FFFFFFF;
0293     wdt->mr = 0;
0294     if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
0295         !strcmp(tmp, "software")) {
0296         wdt->mr |= AT91_WDT_WDFIEN;
0297         wdt->mr_mask &= ~AT91_WDT_WDRPROC;
0298     } else {
0299         wdt->mr |= AT91_WDT_WDRSTEN;
0300     }
0301 
0302     if (!of_property_read_string(np, "atmel,reset-type", &tmp) &&
0303         !strcmp(tmp, "proc"))
0304         wdt->mr |= AT91_WDT_WDRPROC;
0305 
0306     if (of_property_read_bool(np, "atmel,disable")) {
0307         wdt->mr |= AT91_WDT_WDDIS;
0308         wdt->mr_mask &= AT91_WDT_WDDIS;
0309     }
0310 
0311     if (of_property_read_bool(np, "atmel,idle-halt"))
0312         wdt->mr |= AT91_WDT_WDIDLEHLT;
0313 
0314     if (of_property_read_bool(np, "atmel,dbg-halt"))
0315         wdt->mr |= AT91_WDT_WDDBGHLT;
0316 
0317     wdt->mr |= max | ((max - min) << 16);
0318 
0319     return 0;
0320 }
0321 #else
0322 static inline int of_at91wdt_init(struct device_node *np, struct at91wdt *wdt)
0323 {
0324     return 0;
0325 }
0326 #endif
0327 
0328 static int __init at91wdt_probe(struct platform_device *pdev)
0329 {
0330     int err;
0331     struct at91wdt *wdt;
0332 
0333     wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
0334     if (!wdt)
0335         return -ENOMEM;
0336 
0337     wdt->mr = (WDT_HW_TIMEOUT * 256) | AT91_WDT_WDRSTEN | AT91_WDT_WDD |
0338           AT91_WDT_WDDBGHLT | AT91_WDT_WDIDLEHLT;
0339     wdt->mr_mask = 0x3FFFFFFF;
0340     wdt->nowayout = nowayout;
0341     wdt->wdd.parent = &pdev->dev;
0342     wdt->wdd.info = &at91_wdt_info;
0343     wdt->wdd.ops = &at91_wdt_ops;
0344     wdt->wdd.timeout = WDT_HEARTBEAT;
0345     wdt->wdd.min_timeout = 1;
0346     wdt->wdd.max_timeout = 0xFFFF;
0347 
0348     wdt->base = devm_platform_ioremap_resource(pdev, 0);
0349     if (IS_ERR(wdt->base))
0350         return PTR_ERR(wdt->base);
0351 
0352     wdt->sclk = devm_clk_get(&pdev->dev, NULL);
0353     if (IS_ERR(wdt->sclk))
0354         return PTR_ERR(wdt->sclk);
0355 
0356     err = clk_prepare_enable(wdt->sclk);
0357     if (err) {
0358         dev_err(&pdev->dev, "Could not enable slow clock\n");
0359         return err;
0360     }
0361 
0362     if (pdev->dev.of_node) {
0363         err = of_at91wdt_init(pdev->dev.of_node, wdt);
0364         if (err)
0365             goto err_clk;
0366     }
0367 
0368     err = at91_wdt_init(pdev, wdt);
0369     if (err)
0370         goto err_clk;
0371 
0372     platform_set_drvdata(pdev, wdt);
0373 
0374     pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n",
0375         wdt->wdd.timeout, wdt->nowayout);
0376 
0377     return 0;
0378 
0379 err_clk:
0380     clk_disable_unprepare(wdt->sclk);
0381 
0382     return err;
0383 }
0384 
0385 static int __exit at91wdt_remove(struct platform_device *pdev)
0386 {
0387     struct at91wdt *wdt = platform_get_drvdata(pdev);
0388     watchdog_unregister_device(&wdt->wdd);
0389 
0390     pr_warn("I quit now, hardware will probably reboot!\n");
0391     del_timer(&wdt->timer);
0392     clk_disable_unprepare(wdt->sclk);
0393 
0394     return 0;
0395 }
0396 
0397 #if defined(CONFIG_OF)
0398 static const struct of_device_id at91_wdt_dt_ids[] = {
0399     { .compatible = "atmel,at91sam9260-wdt" },
0400     { /* sentinel */ }
0401 };
0402 
0403 MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
0404 #endif
0405 
0406 static struct platform_driver at91wdt_driver = {
0407     .remove     = __exit_p(at91wdt_remove),
0408     .driver     = {
0409         .name   = "at91_wdt",
0410         .of_match_table = of_match_ptr(at91_wdt_dt_ids),
0411     },
0412 };
0413 
0414 module_platform_driver_probe(at91wdt_driver, at91wdt_probe);
0415 
0416 MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>");
0417 MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors");
0418 MODULE_LICENSE("GPL");