Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * drivers/watchdog/shwdt.c
0004  *
0005  * Watchdog driver for integrated watchdog in the SuperH processors.
0006  *
0007  * Copyright (C) 2001 - 2012  Paul Mundt <lethal@linux-sh.org>
0008  *
0009  * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
0010  *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
0011  *
0012  * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
0013  *     Added expect close support, made emulated timeout runtime changeable
0014  *     general cleanups, add some ioctls
0015  */
0016 
0017 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0018 
0019 #include <linux/module.h>
0020 #include <linux/moduleparam.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/init.h>
0023 #include <linux/types.h>
0024 #include <linux/spinlock.h>
0025 #include <linux/watchdog.h>
0026 #include <linux/pm_runtime.h>
0027 #include <linux/fs.h>
0028 #include <linux/mm.h>
0029 #include <linux/slab.h>
0030 #include <linux/io.h>
0031 #include <linux/clk.h>
0032 #include <linux/err.h>
0033 #include <asm/watchdog.h>
0034 
0035 #define DRV_NAME "sh-wdt"
0036 
0037 /*
0038  * Default clock division ratio is 5.25 msecs. For an additional table of
0039  * values, consult the asm-sh/watchdog.h. Overload this at module load
0040  * time.
0041  *
0042  * In order for this to work reliably we need to have HZ set to 1000 or
0043  * something quite higher than 100 (or we need a proper high-res timer
0044  * implementation that will deal with this properly), otherwise the 10ms
0045  * resolution of a jiffy is enough to trigger the overflow. For things like
0046  * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
0047  * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
0048  * necssary.
0049  *
0050  * As a result of this timing problem, the only modes that are particularly
0051  * feasible are the 4096 and the 2048 divisors, which yield 5.25 and 2.62ms
0052  * overflow periods respectively.
0053  *
0054  * Also, since we can't really expect userspace to be responsive enough
0055  * before the overflow happens, we maintain two separate timers .. One in
0056  * the kernel for clearing out WOVF every 2ms or so (again, this depends on
0057  * HZ == 1000), and another for monitoring userspace writes to the WDT device.
0058  *
0059  * As such, we currently use a configurable heartbeat interval which defaults
0060  * to 30s. In this case, the userspace daemon is only responsible for periodic
0061  * writes to the device before the next heartbeat is scheduled. If the daemon
0062  * misses its deadline, the kernel timer will allow the WDT to overflow.
0063  */
0064 static int clock_division_ratio = WTCSR_CKS_4096;
0065 #define next_ping_period(cks)   (jiffies + msecs_to_jiffies(cks - 4))
0066 
0067 #define WATCHDOG_HEARTBEAT 30           /* 30 sec default heartbeat */
0068 static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
0069 static bool nowayout = WATCHDOG_NOWAYOUT;
0070 static unsigned long next_heartbeat;
0071 
0072 struct sh_wdt {
0073     void __iomem        *base;
0074     struct device       *dev;
0075     struct clk      *clk;
0076     spinlock_t      lock;
0077 
0078     struct timer_list   timer;
0079 };
0080 
0081 static int sh_wdt_start(struct watchdog_device *wdt_dev)
0082 {
0083     struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
0084     unsigned long flags;
0085     u8 csr;
0086 
0087     pm_runtime_get_sync(wdt->dev);
0088     clk_enable(wdt->clk);
0089 
0090     spin_lock_irqsave(&wdt->lock, flags);
0091 
0092     next_heartbeat = jiffies + (heartbeat * HZ);
0093     mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
0094 
0095     csr = sh_wdt_read_csr();
0096     csr |= WTCSR_WT | clock_division_ratio;
0097     sh_wdt_write_csr(csr);
0098 
0099     sh_wdt_write_cnt(0);
0100 
0101     /*
0102      * These processors have a bit of an inconsistent initialization
0103      * process.. starting with SH-3, RSTS was moved to WTCSR, and the
0104      * RSTCSR register was removed.
0105      *
0106      * On the SH-2 however, in addition with bits being in different
0107      * locations, we must deal with RSTCSR outright..
0108      */
0109     csr = sh_wdt_read_csr();
0110     csr |= WTCSR_TME;
0111     csr &= ~WTCSR_RSTS;
0112     sh_wdt_write_csr(csr);
0113 
0114 #ifdef CONFIG_CPU_SH2
0115     csr = sh_wdt_read_rstcsr();
0116     csr &= ~RSTCSR_RSTS;
0117     sh_wdt_write_rstcsr(csr);
0118 #endif
0119     spin_unlock_irqrestore(&wdt->lock, flags);
0120 
0121     return 0;
0122 }
0123 
0124 static int sh_wdt_stop(struct watchdog_device *wdt_dev)
0125 {
0126     struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
0127     unsigned long flags;
0128     u8 csr;
0129 
0130     spin_lock_irqsave(&wdt->lock, flags);
0131 
0132     del_timer(&wdt->timer);
0133 
0134     csr = sh_wdt_read_csr();
0135     csr &= ~WTCSR_TME;
0136     sh_wdt_write_csr(csr);
0137 
0138     spin_unlock_irqrestore(&wdt->lock, flags);
0139 
0140     clk_disable(wdt->clk);
0141     pm_runtime_put_sync(wdt->dev);
0142 
0143     return 0;
0144 }
0145 
0146 static int sh_wdt_keepalive(struct watchdog_device *wdt_dev)
0147 {
0148     struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
0149     unsigned long flags;
0150 
0151     spin_lock_irqsave(&wdt->lock, flags);
0152     next_heartbeat = jiffies + (heartbeat * HZ);
0153     spin_unlock_irqrestore(&wdt->lock, flags);
0154 
0155     return 0;
0156 }
0157 
0158 static int sh_wdt_set_heartbeat(struct watchdog_device *wdt_dev, unsigned t)
0159 {
0160     struct sh_wdt *wdt = watchdog_get_drvdata(wdt_dev);
0161     unsigned long flags;
0162 
0163     if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
0164         return -EINVAL;
0165 
0166     spin_lock_irqsave(&wdt->lock, flags);
0167     heartbeat = t;
0168     wdt_dev->timeout = t;
0169     spin_unlock_irqrestore(&wdt->lock, flags);
0170 
0171     return 0;
0172 }
0173 
0174 static void sh_wdt_ping(struct timer_list *t)
0175 {
0176     struct sh_wdt *wdt = from_timer(wdt, t, timer);
0177     unsigned long flags;
0178 
0179     spin_lock_irqsave(&wdt->lock, flags);
0180     if (time_before(jiffies, next_heartbeat)) {
0181         u8 csr;
0182 
0183         csr = sh_wdt_read_csr();
0184         csr &= ~WTCSR_IOVF;
0185         sh_wdt_write_csr(csr);
0186 
0187         sh_wdt_write_cnt(0);
0188 
0189         mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
0190     } else
0191         dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
0192                  "the watchdog\n");
0193     spin_unlock_irqrestore(&wdt->lock, flags);
0194 }
0195 
0196 static const struct watchdog_info sh_wdt_info = {
0197     .options        = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
0198                   WDIOF_MAGICCLOSE,
0199     .firmware_version   = 1,
0200     .identity       = "SH WDT",
0201 };
0202 
0203 static const struct watchdog_ops sh_wdt_ops = {
0204     .owner      = THIS_MODULE,
0205     .start      = sh_wdt_start,
0206     .stop       = sh_wdt_stop,
0207     .ping       = sh_wdt_keepalive,
0208     .set_timeout    = sh_wdt_set_heartbeat,
0209 };
0210 
0211 static struct watchdog_device sh_wdt_dev = {
0212     .info   = &sh_wdt_info,
0213     .ops    = &sh_wdt_ops,
0214 };
0215 
0216 static int sh_wdt_probe(struct platform_device *pdev)
0217 {
0218     struct sh_wdt *wdt;
0219     int rc;
0220 
0221     /*
0222      * As this driver only covers the global watchdog case, reject
0223      * any attempts to register per-CPU watchdogs.
0224      */
0225     if (pdev->id != -1)
0226         return -EINVAL;
0227 
0228     wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
0229     if (unlikely(!wdt))
0230         return -ENOMEM;
0231 
0232     wdt->dev = &pdev->dev;
0233 
0234     wdt->clk = devm_clk_get(&pdev->dev, NULL);
0235     if (IS_ERR(wdt->clk)) {
0236         /*
0237          * Clock framework support is optional, continue on
0238          * anyways if we don't find a matching clock.
0239          */
0240         wdt->clk = NULL;
0241     }
0242 
0243     wdt->base = devm_platform_ioremap_resource(pdev, 0);
0244     if (IS_ERR(wdt->base))
0245         return PTR_ERR(wdt->base);
0246 
0247     watchdog_set_nowayout(&sh_wdt_dev, nowayout);
0248     watchdog_set_drvdata(&sh_wdt_dev, wdt);
0249     sh_wdt_dev.parent = &pdev->dev;
0250 
0251     spin_lock_init(&wdt->lock);
0252 
0253     rc = sh_wdt_set_heartbeat(&sh_wdt_dev, heartbeat);
0254     if (unlikely(rc)) {
0255         /* Default timeout if invalid */
0256         sh_wdt_set_heartbeat(&sh_wdt_dev, WATCHDOG_HEARTBEAT);
0257 
0258         dev_warn(&pdev->dev,
0259              "heartbeat value must be 1<=x<=3600, using %d\n",
0260              sh_wdt_dev.timeout);
0261     }
0262 
0263     dev_info(&pdev->dev, "configured with heartbeat=%d sec (nowayout=%d)\n",
0264          sh_wdt_dev.timeout, nowayout);
0265 
0266     rc = watchdog_register_device(&sh_wdt_dev);
0267     if (unlikely(rc)) {
0268         dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc);
0269         return rc;
0270     }
0271 
0272     timer_setup(&wdt->timer, sh_wdt_ping, 0);
0273     wdt->timer.expires  = next_ping_period(clock_division_ratio);
0274 
0275     dev_info(&pdev->dev, "initialized.\n");
0276 
0277     pm_runtime_enable(&pdev->dev);
0278 
0279     return 0;
0280 }
0281 
0282 static int sh_wdt_remove(struct platform_device *pdev)
0283 {
0284     watchdog_unregister_device(&sh_wdt_dev);
0285 
0286     pm_runtime_disable(&pdev->dev);
0287 
0288     return 0;
0289 }
0290 
0291 static void sh_wdt_shutdown(struct platform_device *pdev)
0292 {
0293     sh_wdt_stop(&sh_wdt_dev);
0294 }
0295 
0296 static struct platform_driver sh_wdt_driver = {
0297     .driver     = {
0298         .name   = DRV_NAME,
0299     },
0300 
0301     .probe      = sh_wdt_probe,
0302     .remove     = sh_wdt_remove,
0303     .shutdown   = sh_wdt_shutdown,
0304 };
0305 
0306 static int __init sh_wdt_init(void)
0307 {
0308     if (unlikely(clock_division_ratio < 0x5 ||
0309              clock_division_ratio > 0x7)) {
0310         clock_division_ratio = WTCSR_CKS_4096;
0311 
0312         pr_info("divisor must be 0x5<=x<=0x7, using %d\n",
0313             clock_division_ratio);
0314     }
0315 
0316     return platform_driver_register(&sh_wdt_driver);
0317 }
0318 
0319 static void __exit sh_wdt_exit(void)
0320 {
0321     platform_driver_unregister(&sh_wdt_driver);
0322 }
0323 module_init(sh_wdt_init);
0324 module_exit(sh_wdt_exit);
0325 
0326 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
0327 MODULE_DESCRIPTION("SuperH watchdog driver");
0328 MODULE_LICENSE("GPL");
0329 MODULE_ALIAS("platform:" DRV_NAME);
0330 
0331 module_param(clock_division_ratio, int, 0);
0332 MODULE_PARM_DESC(clock_division_ratio,
0333     "Clock division ratio. Valid ranges are from 0x5 (1.31ms) "
0334     "to 0x7 (5.25ms). (default=" __MODULE_STRING(WTCSR_CKS_4096) ")");
0335 
0336 module_param(heartbeat, int, 0);
0337 MODULE_PARM_DESC(heartbeat,
0338     "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
0339                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
0340 
0341 module_param(nowayout, bool, 0);
0342 MODULE_PARM_DESC(nowayout,
0343     "Watchdog cannot be stopped once started (default="
0344                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");