of_xilinx_wdt.c revision f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18
1e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* 29419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt 39419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * 4d14fd9645501444f06034339118de56686e25dfbMichal Simek * (C) Copyright 2013 - 2014 Xilinx, Inc. 59419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>) 69419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * 79419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * This program is free software; you can redistribute it and/or 89419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * modify it under the terms of the GNU General Public License 99419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * as published by the Free Software Foundation; either version 109419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek * 2 of the License, or (at your option) any later version. 119419c07ccebf6080159b4440dab9b3e484c96d7aMichal Simek */ 12e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 1327c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1427c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches 15f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek#include <linux/err.h> 16e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/module.h> 17e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/types.h> 18e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/kernel.h> 19e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/ioport.h> 20e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/watchdog.h> 21e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/io.h> 22e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/of.h> 23e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/of_device.h> 24e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#include <linux/of_address.h> 25e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 26e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* Register offsets for the Wdt device */ 27e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_TWCSR0_OFFSET 0x0 /* Control/Status Register0 */ 28e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_TWCSR1_OFFSET 0x4 /* Control/Status Register1 */ 29e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_TBR_OFFSET 0x8 /* Timebase Register Offset */ 30e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 31e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* Control/Status Register Masks */ 32e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status */ 33e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state */ 34e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */ 35e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 36e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* Control/Status Register 0/1 bits */ 37e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */ 38e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 39e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* SelfTest constants */ 40e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000 41e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define XWT_TIMER_FAILED 0xFFFFFFFF 42e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 43e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define WATCHDOG_NAME "Xilinx Watchdog" 44e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera#define PFX WATCHDOG_NAME ": " 45e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 46e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastruct xwdt_device { 47e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera void __iomem *base; 48e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera u32 wdt_interval; 49e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera}; 50e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 51e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic struct xwdt_device xdev; 52e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 53e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic u32 timeout; 54e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic u8 no_timeout; 55e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 56e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic DEFINE_SPINLOCK(spinlock); 57e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 58d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic int xilinx_wdt_start(struct watchdog_device *wdd) 59e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 605cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek u32 control_status_reg; 615cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek 62e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_lock(&spinlock); 63e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 64e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera /* Clean previous status and enable the watchdog timer */ 65e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); 66e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); 67e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 68e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK), 69e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera xdev.base + XWT_TWCSR0_OFFSET); 70e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 71e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET); 72e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 73e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_unlock(&spinlock); 74d14fd9645501444f06034339118de56686e25dfbMichal Simek 75d14fd9645501444f06034339118de56686e25dfbMichal Simek return 0; 76e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera} 77e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 78d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic int xilinx_wdt_stop(struct watchdog_device *wdd) 79e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 805cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek u32 control_status_reg; 815cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek 82e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_lock(&spinlock); 83e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 84e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); 85e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 86e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK), 87e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera xdev.base + XWT_TWCSR0_OFFSET); 88e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 89e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET); 90e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 91e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_unlock(&spinlock); 9227c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_info("Stopped!\n"); 93d14fd9645501444f06034339118de56686e25dfbMichal Simek 94d14fd9645501444f06034339118de56686e25dfbMichal Simek return 0; 95e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera} 96e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 97d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic int xilinx_wdt_keepalive(struct watchdog_device *wdd) 98e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 995cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek u32 control_status_reg; 1005cf4e69d39f6a31a5305d01690c1607356b1483bMichal Simek 101e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_lock(&spinlock); 102e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 103e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET); 104e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK); 105e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET); 106e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 107e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_unlock(&spinlock); 108e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 109d14fd9645501444f06034339118de56686e25dfbMichal Simek return 0; 110d14fd9645501444f06034339118de56686e25dfbMichal Simek} 111e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 112d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic const struct watchdog_info xilinx_wdt_ident = { 113d14fd9645501444f06034339118de56686e25dfbMichal Simek .options = WDIOF_MAGICCLOSE | 114d14fd9645501444f06034339118de56686e25dfbMichal Simek WDIOF_KEEPALIVEPING, 115d14fd9645501444f06034339118de56686e25dfbMichal Simek .firmware_version = 1, 116d14fd9645501444f06034339118de56686e25dfbMichal Simek .identity = WATCHDOG_NAME, 117d14fd9645501444f06034339118de56686e25dfbMichal Simek}; 118e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 119d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic const struct watchdog_ops xilinx_wdt_ops = { 120d14fd9645501444f06034339118de56686e25dfbMichal Simek .owner = THIS_MODULE, 121d14fd9645501444f06034339118de56686e25dfbMichal Simek .start = xilinx_wdt_start, 122d14fd9645501444f06034339118de56686e25dfbMichal Simek .stop = xilinx_wdt_stop, 123d14fd9645501444f06034339118de56686e25dfbMichal Simek .ping = xilinx_wdt_keepalive, 124d14fd9645501444f06034339118de56686e25dfbMichal Simek}; 125e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 126d14fd9645501444f06034339118de56686e25dfbMichal Simekstatic struct watchdog_device xilinx_wdt_wdd = { 127d14fd9645501444f06034339118de56686e25dfbMichal Simek .info = &xilinx_wdt_ident, 128d14fd9645501444f06034339118de56686e25dfbMichal Simek .ops = &xilinx_wdt_ops, 129d14fd9645501444f06034339118de56686e25dfbMichal Simek}; 130e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 131e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic u32 xwdt_selftest(void) 132e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 133e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera int i; 134e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera u32 timer_value1; 135e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera u32 timer_value2; 136e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 137e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_lock(&spinlock); 138e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 139e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET); 140e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET); 141e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 142e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera for (i = 0; 143e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) && 144e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera (timer_value2 == timer_value1)); i++) { 145e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET); 146e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 147e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 148e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera spin_unlock(&spinlock); 149e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 150e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (timer_value2 != timer_value1) 151e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera return ~XWT_TIMER_FAILED; 152e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera else 153e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera return XWT_TIMER_FAILED; 154e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera} 155e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 1562d991a164a61858012651e13c59521975504e260Bill Pembertonstatic int xwdt_probe(struct platform_device *pdev) 157e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 158e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera int rc; 159e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera u32 *tmptr; 160e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera u32 *pfreq; 161f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek struct resource *res; 162e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 163e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera no_timeout = 0; 164e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 165f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 166f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek xdev.base = devm_ioremap_resource(&pdev->dev, res); 167f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek if (IS_ERR(xdev.base)) 168f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek return PTR_ERR(xdev.base); 169f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek 17090fe6c608f8d46e5bb3f31c2d5e1c90475253f79Michal Simek pfreq = (u32 *)of_get_property(pdev->dev.of_node, 171e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera "clock-frequency", NULL); 172e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 173e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (pfreq == NULL) { 17427c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_warn("The watchdog clock frequency cannot be obtained!\n"); 175e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera no_timeout = 1; 176e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 177e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 178e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera tmptr = (u32 *)of_get_property(pdev->dev.of_node, 179e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera "xlnx,wdt-interval", NULL); 180e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (tmptr == NULL) { 18127c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n"); 182e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera no_timeout = 1; 183e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } else { 184e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera xdev.wdt_interval = *tmptr; 185e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 186e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 187e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera tmptr = (u32 *)of_get_property(pdev->dev.of_node, 188e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera "xlnx,wdt-enable-once", NULL); 189e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (tmptr == NULL) { 19027c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); 191d14fd9645501444f06034339118de56686e25dfbMichal Simek watchdog_set_nowayout(&xilinx_wdt_wdd, true); 192e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 193e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 194e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* 195e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera * Twice of the 2^wdt_interval / freq because the first wdt overflow is 196e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera * ignored (interrupt), reset is only generated at second wdt overflow 197e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera */ 198e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (!no_timeout) 199e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq); 200e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 201e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera rc = xwdt_selftest(); 202e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (rc == XWT_TIMER_FAILED) { 20327c766aaacb265d625dc634bf7903f7f9fd0c697Joe Perches pr_err("SelfTest routine error!\n"); 204f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek return rc; 205e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 206e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 207d14fd9645501444f06034339118de56686e25dfbMichal Simek rc = watchdog_register_device(&xilinx_wdt_wdd); 208e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera if (rc) { 209d14fd9645501444f06034339118de56686e25dfbMichal Simek pr_err("cannot register watchdog (err=%d)\n", rc); 210f06cdfd184d845e1f01df7f636c0e3b5c5cc8d18Michal Simek return rc; 211e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera } 212e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 213d14fd9645501444f06034339118de56686e25dfbMichal Simek dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", 214d14fd9645501444f06034339118de56686e25dfbMichal Simek xdev.base, timeout); 215e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 216e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera return 0; 217e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera} 218e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 2194b12b896c27c3b54592816606679f5b02f638930Bill Pembertonstatic int xwdt_remove(struct platform_device *dev) 220e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera{ 221d14fd9645501444f06034339118de56686e25dfbMichal Simek watchdog_unregister_device(&xilinx_wdt_wdd); 222e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 223e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera return 0; 224e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera} 225e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 226e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera/* Match table for of_platform binding */ 2271d1313686422db3bffb2e7bd8eb2ccd9027d3783Bill Pembertonstatic struct of_device_id xwdt_of_match[] = { 2288fce9b367d672332d2d101175b10737ee5c18b59Michal Simek { .compatible = "xlnx,xps-timebase-wdt-1.00.a", }, 229e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera { .compatible = "xlnx,xps-timebase-wdt-1.01.a", }, 230e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera {}, 231e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera}; 232e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro CabreraMODULE_DEVICE_TABLE(of, xwdt_of_match); 233e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 234e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrerastatic struct platform_driver xwdt_driver = { 235e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera .probe = xwdt_probe, 23682268714bdf06bc06135efb707a9de590ab2d294Bill Pemberton .remove = xwdt_remove, 237e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera .driver = { 238e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera .owner = THIS_MODULE, 239e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera .name = WATCHDOG_NAME, 240e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera .of_match_table = xwdt_of_match, 241e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera }, 242e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera}; 243e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 244b8ec61189f3b4cd9d1b2856342f5d7676151d01cAxel Linmodule_platform_driver(xwdt_driver); 245e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro Cabrera 246e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro CabreraMODULE_AUTHOR("Alejandro Cabrera <aldaya@gmail.com>"); 247e9659e69b0094ea2cc92716e2b1cd6a7db9caf2eAlejandro CabreraMODULE_DESCRIPTION("Xilinx Watchdog driver"); 2489419c07ccebf6080159b4440dab9b3e484c96d7aMichal SimekMODULE_LICENSE("GPL v2"); 249