watchdog: of_xilinx_wdt: Add support for reading freq via CCF

Improve CLK handling in the code to read freq via CCF.
Also disable CLK asap and add clk handling code to start and stop.

Signed-off-by: Maulik Jodhani <maulik.jodhani@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
Maulik Jodhani 2017-08-07 13:24:22 +02:00 committed by Wim Van Sebroeck
parent e8a7fc711c
commit b6bc416455

View file

@ -51,9 +51,16 @@ struct xwdt_device {
static int xilinx_wdt_start(struct watchdog_device *wdd) static int xilinx_wdt_start(struct watchdog_device *wdd)
{ {
int ret;
u32 control_status_reg; u32 control_status_reg;
struct xwdt_device *xdev = watchdog_get_drvdata(wdd); struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
ret = clk_enable(xdev->clk);
if (ret) {
dev_err(wdd->parent, "Failed to enable clock\n");
return ret;
}
spin_lock(&xdev->spinlock); spin_lock(&xdev->spinlock);
/* Clean previous status and enable the watchdog timer */ /* Clean previous status and enable the watchdog timer */
@ -85,6 +92,9 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET); iowrite32(0, xdev->base + XWT_TWCSR1_OFFSET);
spin_unlock(&xdev->spinlock); spin_unlock(&xdev->spinlock);
clk_disable(xdev->clk);
pr_info("Stopped!\n"); pr_info("Stopped!\n");
return 0; return 0;
@ -167,11 +177,6 @@ static int xwdt_probe(struct platform_device *pdev)
if (IS_ERR(xdev->base)) if (IS_ERR(xdev->base))
return PTR_ERR(xdev->base); return PTR_ERR(xdev->base);
rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency", &pfreq);
if (rc)
dev_warn(&pdev->dev,
"The watchdog clock frequency cannot be obtained\n");
rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval", rc = of_property_read_u32(pdev->dev.of_node, "xlnx,wdt-interval",
&xdev->wdt_interval); &xdev->wdt_interval);
if (rc) if (rc)
@ -186,6 +191,26 @@ static int xwdt_probe(struct platform_device *pdev)
watchdog_set_nowayout(xilinx_wdt_wdd, enable_once); watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
xdev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(xdev->clk)) {
if (PTR_ERR(xdev->clk) != -ENOENT)
return PTR_ERR(xdev->clk);
/*
* Clock framework support is optional, continue on
* anyways if we don't find a matching clock.
*/
xdev->clk = NULL;
rc = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&pfreq);
if (rc)
dev_warn(&pdev->dev,
"The watchdog clock freq cannot be obtained\n");
} else {
pfreq = clk_get_rate(xdev->clk);
}
/* /*
* Twice of the 2^wdt_interval / freq because the first wdt overflow is * Twice of the 2^wdt_interval / freq because the first wdt overflow is
* ignored (interrupt), reset is only generated at second wdt overflow * ignored (interrupt), reset is only generated at second wdt overflow
@ -197,14 +222,6 @@ static int xwdt_probe(struct platform_device *pdev)
spin_lock_init(&xdev->spinlock); spin_lock_init(&xdev->spinlock);
watchdog_set_drvdata(xilinx_wdt_wdd, xdev); watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
xdev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(xdev->clk)) {
if (PTR_ERR(xdev->clk) == -ENOENT)
xdev->clk = NULL;
else
return PTR_ERR(xdev->clk);
}
rc = clk_prepare_enable(xdev->clk); rc = clk_prepare_enable(xdev->clk);
if (rc) { if (rc) {
dev_err(&pdev->dev, "unable to enable clock\n"); dev_err(&pdev->dev, "unable to enable clock\n");
@ -223,6 +240,8 @@ static int xwdt_probe(struct platform_device *pdev)
goto err_clk_disable; goto err_clk_disable;
} }
clk_disable(xdev->clk);
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, xilinx_wdt_wdd->timeout); xdev->base, xilinx_wdt_wdd->timeout);