1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt 4 * 5 * (C) Copyright 2013 - 2014 Xilinx, Inc. 6 * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>) 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/err.h> 11 #include <linux/module.h> 12 #include <linux/types.h> 13 #include <linux/kernel.h> 14 #include <linux/ioport.h> 15 #include <linux/watchdog.h> 16 #include <linux/io.h> 17 #include <linux/of.h> 18 #include <linux/of_device.h> 19 #include <linux/of_address.h> 20 21 /* Register offsets for the Wdt device */ 22 #define XWT_TWCSR0_OFFSET 0x0 /* Control/Status Register0 */ 23 #define XWT_TWCSR1_OFFSET 0x4 /* Control/Status Register1 */ 24 #define XWT_TBR_OFFSET 0x8 /* Timebase Register Offset */ 25 26 /* Control/Status Register Masks */ 27 #define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status */ 28 #define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state */ 29 #define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */ 30 31 /* Control/Status Register 0/1 bits */ 32 #define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */ 33 34 /* SelfTest constants */ 35 #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000 36 #define XWT_TIMER_FAILED 0xFFFFFFFF 37 38 #define WATCHDOG_NAME "Xilinx Watchdog" 39 40 struct xwdt_device { 41 void __iomem *base; 42 u32 wdt_interval; 43 spinlock_t spinlock; 44 struct watchdog_device xilinx_wdt_wdd; 45 struct clk *clk; 46 }; 47 48 static int xilinx_wdt_start(struct watchdog_device *wdd) 49 { 50 int ret; 51 u32 control_status_reg; 52 struct xwdt_device *xdev = watchdog_get_drvdata(wdd); 53 54 ret = clk_enable(xdev->clk); 55 if (ret) { 56 dev_err(wdd->parent, "Failed to enable clock\n"); 57 return ret; 58 } 59 60 spin_lock(&xdev->spinlock); 61 62 /* Clean previous status and enable the watchdog timer */ 63 control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); 64 control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); 65 66 iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK), 67 xdev->base + XWT_TWCSR0_OFFSET); 68 69 iowrite32(XWT_CSRX_EWDT2_MASK, xdev->base + XWT_TWCSR1_OFFSET); 70 71 spin_unlock(&xdev->spinlock); 72 73 return 0; 74 } 75 76 static int xilinx_wdt_stop(struct watchdog_device *wdd) 77 { 78 u32 control_status_reg; 79 struct xwdt_device *xdev = watchdog_get_drvdata(wdd); 80 81 spin_lock(&xdev->spinlock); 82 83 control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); 84 85 iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK), 86 xdev->base + XWT_TWCSR0_OFFSET); 87 88 iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET); 89 90 spin_unlock(&xdev->spinlock); 91 92 clk_disable(xdev->clk); 93 94 pr_info("Stopped!\n"); 95 96 return 0; 97 } 98 99 static int xilinx_wdt_keepalive(struct watchdog_device *wdd) 100 { 101 u32 control_status_reg; 102 struct xwdt_device *xdev = watchdog_get_drvdata(wdd); 103 104 spin_lock(&xdev->spinlock); 105 106 control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET); 107 control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); 108 iowrite32(control_status_reg, xdev->base + XWT_TWCSR0_OFFSET); 109 110 spin_unlock(&xdev->spinlock); 111 112 return 0; 113 } 114 115 static const struct watchdog_info xilinx_wdt_ident = { 116 .options = WDIOF_MAGICCLOSE | 117 WDIOF_KEEPALIVEPING, 118 .firmware_version = 1, 119 .identity = WATCHDOG_NAME, 120 }; 121 122 static const struct watchdog_ops xilinx_wdt_ops = { 123 .owner = THIS_MODULE, 124 .start = xilinx_wdt_start, 125 .stop = xilinx_wdt_stop, 126 .ping = xilinx_wdt_keepalive, 127 }; 128 129 static u32 xwdt_selftest(struct xwdt_device *xdev) 130 { 131 int i; 132 u32 timer_value1; 133 u32 timer_value2; 134 135 spin_lock(&xdev->spinlock); 136 137 timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET); 138 timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET); 139 140 for (i = 0; 141 ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) && 142 (timer_value2 == timer_value1)); i++) { 143 timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET); 144 } 145 146 spin_unlock(&xdev->spinlock); 147 148 if (timer_value2 != timer_value1) 149 return ~XWT_TIMER_FAILED; 150 else 151 return XWT_TIMER_FAILED; 152 } 153 154 static int xwdt_probe(struct platform_device *pdev) 155 { 156 int rc; 157 u32 pfreq = 0, enable_once = 0; 158 struct resource *res; 159 struct xwdt_device *xdev; 160 struct watchdog_device *xilinx_wdt_wdd; 161 162 xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); 163 if (!xdev) 164 return -ENOMEM; 165 166 xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd; 167 xilinx_wdt_wdd->info = &xilinx_wdt_ident; 168 xilinx_wdt_wdd->ops = &xilinx_wdt_ops; 169 xilinx_wdt_wdd->parent = &pdev->dev; 170 171 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 172 xdev->base = devm_ioremap_resource(&pdev->dev, res); 173 if (IS_ERR(xdev->base)) 174 return PTR_ERR(xdev->base); 175 176 rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval", 177 &xdev->wdt_interval); 178 if (rc) 179 dev_warn(&pdev->dev, 180 "Parameter \"xlnx,wdt-interval\" not found\n"); 181 182 rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-enable-once", 183 &enable_once); 184 if (rc) 185 dev_warn(&pdev->dev, 186 "Parameter \"xlnx,wdt-enable-once\" not found\n"); 187 188 watchdog_set_nowayout(xilinx_wdt_wdd, enable_once); 189 190 xdev->clk = devm_clk_get(&pdev->dev, NULL); 191 if (IS_ERR(xdev->clk)) { 192 if (PTR_ERR(xdev->clk) != -ENOENT) 193 return PTR_ERR(xdev->clk); 194 195 /* 196 * Clock framework support is optional, continue on 197 * anyways if we don't find a matching clock. 198 */ 199 xdev->clk = NULL; 200 201 rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency", 202 &pfreq); 203 if (rc) 204 dev_warn(&pdev->dev, 205 "The watchdog clock freq cannot be obtained\n"); 206 } else { 207 pfreq = clk_get_rate(xdev->clk); 208 } 209 210 /* 211 * Twice of the 2^wdt_interval / freq because the first wdt overflow is 212 * ignored (interrupt), reset is only generated at second wdt overflow 213 */ 214 if (pfreq && xdev->wdt_interval) 215 xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) / 216 pfreq); 217 218 spin_lock_init(&xdev->spinlock); 219 watchdog_set_drvdata(xilinx_wdt_wdd, xdev); 220 221 rc = clk_prepare_enable(xdev->clk); 222 if (rc) { 223 dev_err(&pdev->dev, "unable to enable clock\n"); 224 return rc; 225 } 226 227 rc = xwdt_selftest(xdev); 228 if (rc == XWT_TIMER_FAILED) { 229 dev_err(&pdev->dev, "SelfTest routine error\n"); 230 goto err_clk_disable; 231 } 232 233 rc = watchdog_register_device(xilinx_wdt_wdd); 234 if (rc) { 235 dev_err(&pdev->dev, "Cannot register watchdog (err=%d)\n", rc); 236 goto err_clk_disable; 237 } 238 239 clk_disable(xdev->clk); 240 241 dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", 242 xdev->base, xilinx_wdt_wdd->timeout); 243 244 platform_set_drvdata(pdev, xdev); 245 246 return 0; 247 err_clk_disable: 248 clk_disable_unprepare(xdev->clk); 249 250 return rc; 251 } 252 253 static int xwdt_remove(struct platform_device *pdev) 254 { 255 struct xwdt_device *xdev = platform_get_drvdata(pdev); 256 257 watchdog_unregister_device(&xdev->xilinx_wdt_wdd); 258 clk_disable_unprepare(xdev->clk); 259 260 return 0; 261 } 262 263 /** 264 * xwdt_suspend - Suspend the device. 265 * 266 * @dev: handle to the device structure. 267 * Return: 0 always. 268 */ 269 static int __maybe_unused xwdt_suspend(struct device *dev) 270 { 271 struct xwdt_device *xdev = dev_get_drvdata(dev); 272 273 if (watchdog_active(&xdev->xilinx_wdt_wdd)) 274 xilinx_wdt_stop(&xdev->xilinx_wdt_wdd); 275 276 return 0; 277 } 278 279 /** 280 * xwdt_resume - Resume the device. 281 * 282 * @dev: handle to the device structure. 283 * Return: 0 on success, errno otherwise. 284 */ 285 static int __maybe_unused xwdt_resume(struct device *dev) 286 { 287 struct xwdt_device *xdev = dev_get_drvdata(dev); 288 int ret = 0; 289 290 if (watchdog_active(&xdev->xilinx_wdt_wdd)) 291 ret = xilinx_wdt_start(&xdev->xilinx_wdt_wdd); 292 293 return ret; 294 } 295 296 static SIMPLE_DEV_PM_OPS(xwdt_pm_ops, xwdt_suspend, xwdt_resume); 297 298 /* Match table for of_platform binding */ 299 static const struct of_device_id xwdt_of_match[] = { 300 { .compatible = "xlnx,xps-timebase-wdt-1.00.a", }, 301 { .compatible = "xlnx,xps-timebase-wdt-1.01.a", }, 302 {}, 303 }; 304 MODULE_DEVICE_TABLE(of, xwdt_of_match); 305 306 static struct platform_driver xwdt_driver = { 307 .probe = xwdt_probe, 308 .remove = xwdt_remove, 309 .driver = { 310 .name = WATCHDOG_NAME, 311 .of_match_table = xwdt_of_match, 312 .pm = &xwdt_pm_ops, 313 }, 314 }; 315 316 module_platform_driver(xwdt_driver); 317 318 MODULE_AUTHOR("Alejandro Cabrera <aldaya@gmail.com>"); 319 MODULE_DESCRIPTION("Xilinx Watchdog driver"); 320 MODULE_LICENSE("GPL"); 321