^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * drivers/watchdog/m54xx_wdt.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Watchdog driver for ColdFire MCF547x & MCF548x processors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2010 (c) Philippe De Muyter <phdm@macqel.be>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Adapted from the IXP4xx watchdog driver, which carries these notices:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Deepak Saxena <dsaxena@plexity.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright 2004 (c) MontaVista, Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/watchdog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/coldfire.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/m54xxsim.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/m54xxgpt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static bool nowayout = WATCHDOG_NOWAYOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static unsigned long wdt_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define WDT_IN_USE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define WDT_OK_TO_CLOSE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void wdt_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int gms0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* preserve GPIO usage, if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) gms0 = __raw_readl(MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (gms0 & MCF_GPT_GMS_TMS_GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) | MCF_GPT_GMS_OD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __raw_writel(gms0, MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) MCF_GPT_GCIR_CNT(0xffff), MCF_GPT_GCIR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) __raw_writel(gms0, MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void wdt_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int gms0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* disable watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) gms0 = __raw_readl(MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) __raw_writel(gms0, MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void wdt_keepalive(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int gms0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) gms0 = __raw_readl(MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) gms0 |= MCF_GPT_GMS_OCPW(0xA5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) __raw_writel(gms0, MCF_GPT_GMS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int m54xx_wdt_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (test_and_set_bit(WDT_IN_USE, &wdt_status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) wdt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return stream_open(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static ssize_t m54xx_wdt_write(struct file *file, const char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) size_t len, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!nowayout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) for (i = 0; i != len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (get_user(c, data + i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (c == 'V')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) set_bit(WDT_OK_TO_CLOSE, &wdt_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) wdt_keepalive();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static const struct watchdog_info ident = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) WDIOF_KEEPALIVEPING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .identity = "Coldfire M54xx Watchdog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static long m54xx_wdt_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int ret = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case WDIOC_GETSUPPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ret = copy_to_user((struct watchdog_info *)arg, &ident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sizeof(ident)) ? -EFAULT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case WDIOC_GETSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = put_user(0, (int *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case WDIOC_GETBOOTSTATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ret = put_user(0, (int *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case WDIOC_KEEPALIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) wdt_keepalive();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case WDIOC_SETTIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = get_user(time, (int *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (time <= 0 || time > 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) heartbeat = time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) wdt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case WDIOC_GETTIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ret = put_user(heartbeat, (int *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int m54xx_wdt_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) wdt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) pr_crit("Device closed unexpectedly - timer will not stop\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) wdt_keepalive();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) clear_bit(WDT_IN_USE, &wdt_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const struct file_operations m54xx_wdt_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .write = m54xx_wdt_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .unlocked_ioctl = m54xx_wdt_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .compat_ioctl = compat_ptr_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .open = m54xx_wdt_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .release = m54xx_wdt_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static struct miscdevice m54xx_wdt_miscdev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .minor = WATCHDOG_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .name = "watchdog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .fops = &m54xx_wdt_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int __init m54xx_wdt_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!request_mem_region(MCF_GPT_GCIR0, 4, "Coldfire M54xx Watchdog")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pr_warn("I/O region busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pr_info("driver is loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return misc_register(&m54xx_wdt_miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static void __exit m54xx_wdt_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) misc_deregister(&m54xx_wdt_miscdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) release_mem_region(MCF_GPT_GCIR0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) module_init(m54xx_wdt_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) module_exit(m54xx_wdt_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) MODULE_DESCRIPTION("Coldfire M54xx Watchdog");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) module_param(heartbeat, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) module_param(nowayout, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) MODULE_LICENSE("GPL");