0001
0002
0003
0004
0005
0006
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/types.h>
0012 #include <linux/fs.h>
0013 #include <linux/errno.h>
0014 #include <linux/miscdevice.h>
0015 #include <linux/watchdog.h>
0016 #include <linux/of.h>
0017 #include <linux/of_device.h>
0018 #include <linux/io.h>
0019 #include <linux/uaccess.h>
0020 #include <linux/slab.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
0048 MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO");
0049 MODULE_LICENSE("GPL");
0050
0051 #define DRIVER_NAME "riowd"
0052 #define PFX DRIVER_NAME ": "
0053
0054 struct riowd {
0055 void __iomem *regs;
0056 spinlock_t lock;
0057 };
0058
0059 static struct riowd *riowd_device;
0060
0061 #define WDTO_INDEX 0x05
0062
0063 static int riowd_timeout = 1;
0064 module_param(riowd_timeout, int, 0);
0065 MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes");
0066
0067 static void riowd_writereg(struct riowd *p, u8 val, int index)
0068 {
0069 unsigned long flags;
0070
0071 spin_lock_irqsave(&p->lock, flags);
0072 writeb(index, p->regs + 0);
0073 writeb(val, p->regs + 1);
0074 spin_unlock_irqrestore(&p->lock, flags);
0075 }
0076
0077 static int riowd_open(struct inode *inode, struct file *filp)
0078 {
0079 stream_open(inode, filp);
0080 return 0;
0081 }
0082
0083 static int riowd_release(struct inode *inode, struct file *filp)
0084 {
0085 return 0;
0086 }
0087
0088 static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
0089 {
0090 static const struct watchdog_info info = {
0091 .options = WDIOF_SETTIMEOUT,
0092 .firmware_version = 1,
0093 .identity = DRIVER_NAME,
0094 };
0095 void __user *argp = (void __user *)arg;
0096 struct riowd *p = riowd_device;
0097 unsigned int options;
0098 int new_margin;
0099
0100 switch (cmd) {
0101 case WDIOC_GETSUPPORT:
0102 if (copy_to_user(argp, &info, sizeof(info)))
0103 return -EFAULT;
0104 break;
0105
0106 case WDIOC_GETSTATUS:
0107 case WDIOC_GETBOOTSTATUS:
0108 if (put_user(0, (int __user *)argp))
0109 return -EFAULT;
0110 break;
0111
0112 case WDIOC_KEEPALIVE:
0113 riowd_writereg(p, riowd_timeout, WDTO_INDEX);
0114 break;
0115
0116 case WDIOC_SETOPTIONS:
0117 if (copy_from_user(&options, argp, sizeof(options)))
0118 return -EFAULT;
0119
0120 if (options & WDIOS_DISABLECARD)
0121 riowd_writereg(p, 0, WDTO_INDEX);
0122 else if (options & WDIOS_ENABLECARD)
0123 riowd_writereg(p, riowd_timeout, WDTO_INDEX);
0124 else
0125 return -EINVAL;
0126
0127 break;
0128
0129 case WDIOC_SETTIMEOUT:
0130 if (get_user(new_margin, (int __user *)argp))
0131 return -EFAULT;
0132 if ((new_margin < 60) || (new_margin > (255 * 60)))
0133 return -EINVAL;
0134 riowd_timeout = (new_margin + 59) / 60;
0135 riowd_writereg(p, riowd_timeout, WDTO_INDEX);
0136 fallthrough;
0137
0138 case WDIOC_GETTIMEOUT:
0139 return put_user(riowd_timeout * 60, (int __user *)argp);
0140
0141 default:
0142 return -EINVAL;
0143 }
0144
0145 return 0;
0146 }
0147
0148 static ssize_t riowd_write(struct file *file, const char __user *buf,
0149 size_t count, loff_t *ppos)
0150 {
0151 struct riowd *p = riowd_device;
0152
0153 if (count) {
0154 riowd_writereg(p, riowd_timeout, WDTO_INDEX);
0155 return 1;
0156 }
0157
0158 return 0;
0159 }
0160
0161 static const struct file_operations riowd_fops = {
0162 .owner = THIS_MODULE,
0163 .llseek = no_llseek,
0164 .unlocked_ioctl = riowd_ioctl,
0165 .compat_ioctl = compat_ptr_ioctl,
0166 .open = riowd_open,
0167 .write = riowd_write,
0168 .release = riowd_release,
0169 };
0170
0171 static struct miscdevice riowd_miscdev = {
0172 .minor = WATCHDOG_MINOR,
0173 .name = "watchdog",
0174 .fops = &riowd_fops
0175 };
0176
0177 static int riowd_probe(struct platform_device *op)
0178 {
0179 struct riowd *p;
0180 int err = -EINVAL;
0181
0182 if (riowd_device)
0183 goto out;
0184
0185 err = -ENOMEM;
0186 p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
0187 if (!p)
0188 goto out;
0189
0190 spin_lock_init(&p->lock);
0191
0192 p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME);
0193 if (!p->regs) {
0194 pr_err("Cannot map registers\n");
0195 goto out;
0196 }
0197
0198 riowd_device = p;
0199
0200 err = misc_register(&riowd_miscdev);
0201 if (err) {
0202 pr_err("Cannot register watchdog misc device\n");
0203 goto out_iounmap;
0204 }
0205
0206 pr_info("Hardware watchdog [%i minutes], regs at %p\n",
0207 riowd_timeout, p->regs);
0208
0209 platform_set_drvdata(op, p);
0210 return 0;
0211
0212 out_iounmap:
0213 riowd_device = NULL;
0214 of_iounmap(&op->resource[0], p->regs, 2);
0215
0216 out:
0217 return err;
0218 }
0219
0220 static int riowd_remove(struct platform_device *op)
0221 {
0222 struct riowd *p = platform_get_drvdata(op);
0223
0224 misc_deregister(&riowd_miscdev);
0225 of_iounmap(&op->resource[0], p->regs, 2);
0226
0227 return 0;
0228 }
0229
0230 static const struct of_device_id riowd_match[] = {
0231 {
0232 .name = "pmc",
0233 },
0234 {},
0235 };
0236 MODULE_DEVICE_TABLE(of, riowd_match);
0237
0238 static struct platform_driver riowd_driver = {
0239 .driver = {
0240 .name = DRIVER_NAME,
0241 .of_match_table = riowd_match,
0242 },
0243 .probe = riowd_probe,
0244 .remove = riowd_remove,
0245 };
0246
0247 module_platform_driver(riowd_driver);