Commit 90663171 authored by Michal Simek's avatar Michal Simek Committed by Wim Van Sebroeck

watchdog: xilinx: Allocate private structure per device

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: default avatarMichal Simek <michal.simek@xilinx.com>
Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
parent ffb8eee4
...@@ -46,30 +46,27 @@ ...@@ -46,30 +46,27 @@
struct xwdt_device { struct xwdt_device {
void __iomem *base; void __iomem *base;
u32 wdt_interval; 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) static int xilinx_wdt_start(struct watchdog_device *wdd)
{ {
u32 control_status_reg; 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 */ /* 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); control_status_reg |= (XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK);
iowrite32((control_status_reg | XWT_CSR0_EWDT1_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; return 0;
} }
...@@ -77,17 +74,18 @@ static int xilinx_wdt_start(struct watchdog_device *wdd) ...@@ -77,17 +74,18 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
static int xilinx_wdt_stop(struct watchdog_device *wdd) static int xilinx_wdt_stop(struct watchdog_device *wdd)
{ {
u32 control_status_reg; 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), 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"); pr_info("Stopped!\n");
return 0; return 0;
...@@ -96,14 +94,15 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd) ...@@ -96,14 +94,15 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
static int xilinx_wdt_keepalive(struct watchdog_device *wdd) static int xilinx_wdt_keepalive(struct watchdog_device *wdd)
{ {
u32 control_status_reg; 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); 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; return 0;
} }
...@@ -122,29 +121,24 @@ static const struct watchdog_ops xilinx_wdt_ops = { ...@@ -122,29 +121,24 @@ static const struct watchdog_ops xilinx_wdt_ops = {
.ping = xilinx_wdt_keepalive, .ping = xilinx_wdt_keepalive,
}; };
static struct watchdog_device xilinx_wdt_wdd = { static u32 xwdt_selftest(struct xwdt_device *xdev)
.info = &xilinx_wdt_ident,
.ops = &xilinx_wdt_ops,
};
static u32 xwdt_selftest(void)
{ {
int i; int i;
u32 timer_value1; u32 timer_value1;
u32 timer_value2; u32 timer_value2;
spin_lock(&spinlock); spin_lock(&xdev->spinlock);
timer_value1 = ioread32(xdev.base + XWT_TBR_OFFSET); timer_value1 = ioread32(xdev->base + XWT_TBR_OFFSET);
timer_value2 = ioread32(xdev.base + XWT_TBR_OFFSET); timer_value2 = ioread32(xdev->base + XWT_TBR_OFFSET);
for (i = 0; for (i = 0;
((i <= XWT_MAX_SELFTEST_LOOP_COUNT) && ((i <= XWT_MAX_SELFTEST_LOOP_COUNT) &&
(timer_value2 == timer_value1)); i++) { (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) if (timer_value2 != timer_value1)
return ~XWT_TIMER_FAILED; return ~XWT_TIMER_FAILED;
...@@ -158,12 +152,23 @@ static int xwdt_probe(struct platform_device *pdev) ...@@ -158,12 +152,23 @@ static int xwdt_probe(struct platform_device *pdev)
u32 *tmptr; u32 *tmptr;
u32 *pfreq; u32 *pfreq;
struct resource *res; struct resource *res;
struct xwdt_device *xdev;
bool no_timeout = false; 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); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xdev.base = devm_ioremap_resource(&pdev->dev, res); xdev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xdev.base)) if (IS_ERR(xdev->base))
return PTR_ERR(xdev.base); return PTR_ERR(xdev->base);
pfreq = (u32 *)of_get_property(pdev->dev.of_node, pfreq = (u32 *)of_get_property(pdev->dev.of_node,
"clock-frequency", NULL); "clock-frequency", NULL);
...@@ -179,14 +184,14 @@ static int xwdt_probe(struct platform_device *pdev) ...@@ -179,14 +184,14 @@ static int xwdt_probe(struct platform_device *pdev)
pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n"); pr_warn("Parameter \"xlnx,wdt-interval\" not found in device tree!\n");
no_timeout = true; no_timeout = true;
} else { } else {
xdev.wdt_interval = *tmptr; xdev->wdt_interval = *tmptr;
} }
tmptr = (u32 *)of_get_property(pdev->dev.of_node, tmptr = (u32 *)of_get_property(pdev->dev.of_node,
"xlnx,wdt-enable-once", NULL); "xlnx,wdt-enable-once", NULL);
if (tmptr == NULL) { if (tmptr == NULL) {
pr_warn("Parameter \"xlnx,wdt-enable-once\" not found in device tree!\n"); 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) ...@@ -194,29 +199,37 @@ static int xwdt_probe(struct platform_device *pdev)
* ignored (interrupt), reset is only generated at second wdt overflow * ignored (interrupt), reset is only generated at second wdt overflow
*/ */
if (!no_timeout) 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) { if (rc == XWT_TIMER_FAILED) {
pr_err("SelfTest routine error!\n"); pr_err("SelfTest routine error!\n");
return rc; return rc;
} }
rc = watchdog_register_device(&xilinx_wdt_wdd); rc = watchdog_register_device(xilinx_wdt_wdd);
if (rc) { if (rc) {
pr_err("cannot register watchdog (err=%d)\n", rc); pr_err("cannot register watchdog (err=%d)\n", rc);
return rc; return rc;
} }
dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", 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; 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment