1 /* 2 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface 3 * 4 * Authors: Dave Updegraff <dave@cray.org> 5 * Kumar Gala <galak@kernel.crashing.org> 6 * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> 7 * ..and from sc520_wdt 8 * Copyright (c) 2008 MontaVista Software, Inc. 9 * Anton Vorontsov <avorontsov@ru.mvista.com> 10 * 11 * Note: it appears that you can only actually ENABLE or DISABLE the thing 12 * once after POR. Once enabled, you cannot disable, and vice versa. 13 * 14 * This program is free software; you can redistribute it and/or modify it 15 * under the terms of the GNU General Public License as published by the 16 * Free Software Foundation; either version 2 of the License, or (at your 17 * option) any later version. 18 */ 19 20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 21 22 #include <linux/fs.h> 23 #include <linux/init.h> 24 #include <linux/kernel.h> 25 #include <linux/of_address.h> 26 #include <linux/of_platform.h> 27 #include <linux/module.h> 28 #include <linux/watchdog.h> 29 #include <linux/io.h> 30 #include <linux/uaccess.h> 31 #include <sysdev/fsl_soc.h> 32 33 #define WATCHDOG_TIMEOUT 10 34 35 struct mpc8xxx_wdt { 36 __be32 res0; 37 __be32 swcrr; /* System watchdog control register */ 38 #define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ 39 #define SWCRR_SWF 0x00000008 /* Software Watchdog Freeze (mpc8xx). */ 40 #define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ 41 #define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ 42 #define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ 43 __be32 swcnr; /* System watchdog count register */ 44 u8 res1[2]; 45 __be16 swsrr; /* System watchdog service register */ 46 u8 res2[0xF0]; 47 }; 48 49 struct mpc8xxx_wdt_type { 50 int prescaler; 51 bool hw_enabled; 52 }; 53 54 struct mpc8xxx_wdt_ddata { 55 struct mpc8xxx_wdt __iomem *base; 56 struct watchdog_device wdd; 57 spinlock_t lock; 58 u16 swtc; 59 }; 60 61 static u16 timeout; 62 module_param(timeout, ushort, 0); 63 MODULE_PARM_DESC(timeout, 64 "Watchdog timeout in seconds. (1<timeout<65535, default=" 65 __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 66 67 static bool reset = 1; 68 module_param(reset, bool, 0); 69 MODULE_PARM_DESC(reset, 70 "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset"); 71 72 static bool nowayout = WATCHDOG_NOWAYOUT; 73 module_param(nowayout, bool, 0); 74 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 75 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 76 77 static void mpc8xxx_wdt_keepalive(struct mpc8xxx_wdt_ddata *ddata) 78 { 79 /* Ping the WDT */ 80 spin_lock(&ddata->lock); 81 out_be16(&ddata->base->swsrr, 0x556c); 82 out_be16(&ddata->base->swsrr, 0xaa39); 83 spin_unlock(&ddata->lock); 84 } 85 86 static int mpc8xxx_wdt_start(struct watchdog_device *w) 87 { 88 struct mpc8xxx_wdt_ddata *ddata = 89 container_of(w, struct mpc8xxx_wdt_ddata, wdd); 90 u32 tmp = in_be32(&ddata->base->swcrr); 91 92 /* Good, fire up the show */ 93 tmp &= ~(SWCRR_SWTC | SWCRR_SWF | SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR); 94 tmp |= SWCRR_SWEN | SWCRR_SWPR | (ddata->swtc << 16); 95 96 if (reset) 97 tmp |= SWCRR_SWRI; 98 99 out_be32(&ddata->base->swcrr, tmp); 100 101 tmp = in_be32(&ddata->base->swcrr); 102 if (!(tmp & SWCRR_SWEN)) 103 return -EOPNOTSUPP; 104 105 ddata->swtc = tmp >> 16; 106 set_bit(WDOG_HW_RUNNING, &ddata->wdd.status); 107 108 return 0; 109 } 110 111 static int mpc8xxx_wdt_ping(struct watchdog_device *w) 112 { 113 struct mpc8xxx_wdt_ddata *ddata = 114 container_of(w, struct mpc8xxx_wdt_ddata, wdd); 115 116 mpc8xxx_wdt_keepalive(ddata); 117 return 0; 118 } 119 120 static struct watchdog_info mpc8xxx_wdt_info = { 121 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT, 122 .firmware_version = 1, 123 .identity = "MPC8xxx", 124 }; 125 126 static struct watchdog_ops mpc8xxx_wdt_ops = { 127 .owner = THIS_MODULE, 128 .start = mpc8xxx_wdt_start, 129 .ping = mpc8xxx_wdt_ping, 130 }; 131 132 static int mpc8xxx_wdt_probe(struct platform_device *ofdev) 133 { 134 int ret; 135 struct resource *res; 136 const struct mpc8xxx_wdt_type *wdt_type; 137 struct mpc8xxx_wdt_ddata *ddata; 138 u32 freq = fsl_get_sys_freq(); 139 bool enabled; 140 141 wdt_type = of_device_get_match_data(&ofdev->dev); 142 if (!wdt_type) 143 return -EINVAL; 144 145 if (!freq || freq == -1) 146 return -EINVAL; 147 148 ddata = devm_kzalloc(&ofdev->dev, sizeof(*ddata), GFP_KERNEL); 149 if (!ddata) 150 return -ENOMEM; 151 152 res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); 153 ddata->base = devm_ioremap_resource(&ofdev->dev, res); 154 if (IS_ERR(ddata->base)) 155 return PTR_ERR(ddata->base); 156 157 enabled = in_be32(&ddata->base->swcrr) & SWCRR_SWEN; 158 if (!enabled && wdt_type->hw_enabled) { 159 pr_info("could not be enabled in software\n"); 160 return -ENODEV; 161 } 162 163 spin_lock_init(&ddata->lock); 164 165 ddata->wdd.info = &mpc8xxx_wdt_info, 166 ddata->wdd.ops = &mpc8xxx_wdt_ops, 167 168 ddata->wdd.timeout = WATCHDOG_TIMEOUT; 169 watchdog_init_timeout(&ddata->wdd, timeout, &ofdev->dev); 170 171 watchdog_set_nowayout(&ddata->wdd, nowayout); 172 173 ddata->swtc = min(ddata->wdd.timeout * freq / wdt_type->prescaler, 174 0xffffU); 175 176 /* 177 * If the watchdog was previously enabled or we're running on 178 * MPC8xxx, we should ping the wdt from the kernel until the 179 * userspace handles it. 180 */ 181 if (enabled) 182 mpc8xxx_wdt_start(&ddata->wdd); 183 184 ddata->wdd.max_hw_heartbeat_ms = (ddata->swtc * wdt_type->prescaler) / 185 (freq / 1000); 186 ddata->wdd.min_timeout = ddata->wdd.max_hw_heartbeat_ms / 1000; 187 if (ddata->wdd.timeout < ddata->wdd.min_timeout) 188 ddata->wdd.timeout = ddata->wdd.min_timeout; 189 190 ret = watchdog_register_device(&ddata->wdd); 191 if (ret) { 192 pr_err("cannot register watchdog device (err=%d)\n", ret); 193 return ret; 194 } 195 196 pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d sec\n", 197 reset ? "reset" : "interrupt", ddata->wdd.timeout); 198 199 platform_set_drvdata(ofdev, ddata); 200 return 0; 201 } 202 203 static int mpc8xxx_wdt_remove(struct platform_device *ofdev) 204 { 205 struct mpc8xxx_wdt_ddata *ddata = platform_get_drvdata(ofdev); 206 207 pr_crit("Watchdog removed, expect the %s soon!\n", 208 reset ? "reset" : "machine check exception"); 209 watchdog_unregister_device(&ddata->wdd); 210 211 return 0; 212 } 213 214 static const struct of_device_id mpc8xxx_wdt_match[] = { 215 { 216 .compatible = "mpc83xx_wdt", 217 .data = &(struct mpc8xxx_wdt_type) { 218 .prescaler = 0x10000, 219 }, 220 }, 221 { 222 .compatible = "fsl,mpc8610-wdt", 223 .data = &(struct mpc8xxx_wdt_type) { 224 .prescaler = 0x10000, 225 .hw_enabled = true, 226 }, 227 }, 228 { 229 .compatible = "fsl,mpc823-wdt", 230 .data = &(struct mpc8xxx_wdt_type) { 231 .prescaler = 0x800, 232 .hw_enabled = true, 233 }, 234 }, 235 {}, 236 }; 237 MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); 238 239 static struct platform_driver mpc8xxx_wdt_driver = { 240 .probe = mpc8xxx_wdt_probe, 241 .remove = mpc8xxx_wdt_remove, 242 .driver = { 243 .name = "mpc8xxx_wdt", 244 .of_match_table = mpc8xxx_wdt_match, 245 }, 246 }; 247 248 static int __init mpc8xxx_wdt_init(void) 249 { 250 return platform_driver_register(&mpc8xxx_wdt_driver); 251 } 252 arch_initcall(mpc8xxx_wdt_init); 253 254 static void __exit mpc8xxx_wdt_exit(void) 255 { 256 platform_driver_unregister(&mpc8xxx_wdt_driver); 257 } 258 module_exit(mpc8xxx_wdt_exit); 259 260 MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); 261 MODULE_DESCRIPTION("Driver for watchdog timer in MPC8xx/MPC83xx/MPC86xx " 262 "uProcessors"); 263 MODULE_LICENSE("GPL"); 264