0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
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
0068 static int heartbeat = WATCHDOG_HEARTBEAT;
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
0103
0104
0105
0106
0107
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))
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
0223
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
0238
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
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) ")");