watchdog: xilinx: Allocate private structure per device
authorMichal Simek <michal.simek@xilinx.com>
Wed, 12 Feb 2014 13:41:19 +0000 (14:41 +0100)
committerWim Van Sebroeck <wim@iguana.be>
Mon, 31 Mar 2014 11:29:11 +0000 (13:29 +0200)
Only one watchdog could be used by this driver.
Create driver private data structure and move there
all variables for one instance.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
drivers/watchdog/of_xilinx_wdt.c

index 3bc648f40e1f248e09170293c22bc183dc8fd269..ac3f6ebd0c23e811fc1f94f577af12e66c157461 100644 (file)
 struct xwdt_device {
        void __iomem *base;
        u32 wdt_interval;
+       spinlock_t spinlock;
+       struct watchdog_device xilinx_wdt_wdd;
 };
 
-static struct xwdt_device xdev;
-
-static  u32 timeout;
-
-static  DEFINE_SPINLOCK(spinlock);
-
 static int xilinx_wdt_start(struct watchdog_device *wdd)
 {
        u32 control_status_reg;
+       struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
 
-       spin_lock(&spinlock);
+       spin_lock(&xdev->spinlock);
 
        /* Clean previous status and enable the watchdog timer */
-       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
        control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
 
        iowrite32((control_status_reg | XWT_CSR0_EWDT1_MASK),
-                               xdev.base + XWT_TWCSR0_OFFSET);
+                 xdev->base + XWT_TWCSR0_OFFSET);
 
-       iowrite32(XWT_CSRX_EWDT2_MASK, xdev.base + XWT_TWCSR1_OFFSET);
+       iowrite32(XWT_CSRX_EWDT2_MASK, xdev->base + XWT_TWCSR1_OFFSET);
 
-       spin_unlock(&spinlock);
+       spin_unlock(&xdev->spinlock);
 
        return 0;
 }
@@ -77,17 +74,18 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
 static int xilinx_wdt_stop(struct watchdog_device *wdd)
 {
        u32 control_status_reg;
+       struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
 
-       spin_lock(&spinlock);
+       spin_lock(&xdev->spinlock);
 
-       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
 
        iowrite32((control_status_reg & ~XWT_CSR0_EWDT1_MASK),
-                               xdev.base + XWT_TWCSR0_OFFSET);
+                 xdev->base + XWT_TWCSR0_OFFSET);
 
-       iowrite32(0, xdev.base + XWT_TWCSR1_OFFSET);
+       iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET);
 
-       spin_unlock(&spinlock);
+       spin_unlock(&xdev->spinlock);
        pr_info("Stopped!\n");
 
        return 0;
@@ -96,14 +94,15 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
 static int xilinx_wdt_keepalive(struct watchdog_device *wdd)
 {
        u32 control_status_reg;
+       struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
 
-       spin_lock(&spinlock);
+       spin_lock(&xdev->spinlock);
 
-       control_status_reg = ioread32(xdev.base + XWT_TWCSR0_OFFSET);
+       control_status_reg = ioread32(xdev->base + XWT_TWCSR0_OFFSET);
        control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
-       iowrite32(control_status_reg, xdev.base + XWT_TWCSR0_OFFSET);
+       iowrite32(control_status_reg, xdev->base + XWT_TWCSR0_OFFSET);
 
-       spin_unlock(&spinlock);
+       spin_unlock(&xdev->spinlock);
 
        return 0;
 }
@@ -122,29 +121,24 @@ static const struct watchdog_ops xilinx_wdt_ops = {
        .ping = xilinx_wdt_keepalive,
 };
 
-static struct watchdog_device xilinx_wdt_wdd = {
-       .info = &xilinx_wdt_ident,
-       .ops = &xilinx_wdt_ops,
-};
-
-static u32 xwdt_selftest(void)
+static u32 xwdt_selftest(struct xwdt_device *xdev)
 {
        int i;
        u32 timer_value1;
        u32 timer_value2;
 
-       spin_lock(&spinlock);
+       spin_lock(&xdev->spinlock);
 
-       timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET);
-       timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+       timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET);
+       timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
 
        for (i = 0;
                ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) &&
                        (timer_value2 == timer_value1)); i++) {
-               timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET);
+               timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
        }
 
-       spin_unlock(&spinlock);
+       spin_unlock(&xdev->spinlock);
 
        if (timer_value2 != timer_value1)
                return ~XWT_TIMER_FAILED;
@@ -158,12 +152,23 @@ static int xwdt_probe(struct platform_device *pdev)
        u32 *tmptr;
        u32 *pfreq;
        struct resource *res;
+       struct xwdt_device *xdev;
        bool no_timeout = false;
+       struct watchdog_device *xilinx_wdt_wdd;
+
+       xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+       if (!xdev)
+               return -ENOMEM;
+
+       xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+       xilinx_wdt_wdd->info = &xilinx_wdt_ident;
+       xilinx_wdt_wdd->ops = &xilinx_wdt_ops;
+       xilinx_wdt_wdd->parent = &pdev->dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       xdev.base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(xdev.base))
-               return PTR_ERR(xdev.base);
+       xdev->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(xdev->base))
+               return PTR_ERR(xdev->base);
 
        pfreq = (u32 *)of_get_property(pdev->dev.of_node,
                                        "clock-frequency", NULL);
@@ -179,14 +184,14 @@ static int xwdt_probe(struct platform_device *pdev)
                pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
                no_timeout = true;
        } else {
-               xdev.wdt_interval = *tmptr;
+               xdev->wdt_interval = *tmptr;
        }
 
        tmptr = (u32 *)of_get_property(pdev->dev.of_node,
                                        "xlnx,wdt-enable-once", NULL);
        if (tmptr == NULL) {
                pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n");
-               watchdog_set_nowayout(&xilinx_wdt_wdd, true);
+               watchdog_set_nowayout(xilinx_wdt_wdd, true);
        }
 
 /*
@@ -194,29 +199,37 @@ static int xwdt_probe(struct platform_device *pdev)
  *  ignored (interrupt), reset is only generated at second wdt overflow
  */
        if (!no_timeout)
-               timeout = 2 * ((1<<xdev.wdt_interval) / *pfreq);
+               xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
+                                         *pfreq);
+
+       spin_lock_init(&xdev->spinlock);
+       watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
 
-       rc = xwdt_selftest();
+       rc = xwdt_selftest(xdev);
        if (rc == XWT_TIMER_FAILED) {
                pr_err("SelfTest routine error!\n");
                return rc;
        }
 
-       rc = watchdog_register_device(&xilinx_wdt_wdd);
+       rc = watchdog_register_device(xilinx_wdt_wdd);
        if (rc) {
                pr_err("cannot register watchdog (err=%d)\n", rc);
                return rc;
        }
 
        dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
-                xdev.base, timeout);
+                xdev->base, xilinx_wdt_wdd->timeout);
+
+       platform_set_drvdata(pdev, xdev);
 
        return 0;
 }
 
-static int xwdt_remove(struct platform_device *dev)
+static int xwdt_remove(struct platform_device *pdev)
 {
-       watchdog_unregister_device(&xilinx_wdt_wdd);
+       struct xwdt_device *xdev = platform_get_drvdata(pdev);
+
+       watchdog_unregister_device(&xdev->xilinx_wdt_wdd);
 
        return 0;
 }