diff options
Diffstat (limited to 'drivers/watchdog/asm9260_wdt.c')
-rw-r--r-- | drivers/watchdog/asm9260_wdt.c | 77 |
1 files changed, 30 insertions, 47 deletions
diff --git a/drivers/watchdog/asm9260_wdt.c b/drivers/watchdog/asm9260_wdt.c index 9768e44ffeb8..c5b9aae544dd 100644 --- a/drivers/watchdog/asm9260_wdt.c +++ b/drivers/watchdog/asm9260_wdt.c @@ -196,6 +196,11 @@ static const struct watchdog_ops asm9260_wdt_ops = { .restart = asm9260_restart, }; +static void asm9260_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int asm9260_wdt_get_dt_clks(struct asm9260_wdt_priv *priv) { int err; @@ -219,26 +224,32 @@ static int asm9260_wdt_get_dt_clks(struct asm9260_wdt_priv *priv) dev_err(priv->dev, "Failed to enable ahb_clk!\n"); return err; } + err = devm_add_action_or_reset(priv->dev, + asm9260_clk_disable_unprepare, + priv->clk_ahb); + if (err) + return err; err = clk_set_rate(priv->clk, CLOCK_FREQ); if (err) { - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed to set rate!\n"); return err; } err = clk_prepare_enable(priv->clk); if (err) { - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed to enable clk!\n"); return err; } + err = devm_add_action_or_reset(priv->dev, + asm9260_clk_disable_unprepare, + priv->clk); + if (err) + return err; /* wdt has internal divider */ clk = clk_get_rate(priv->clk); if (!clk) { - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); dev_err(priv->dev, "Failed, clk is 0!\n"); return -EINVAL; } @@ -274,25 +285,23 @@ static void asm9260_wdt_get_dt_mode(struct asm9260_wdt_priv *priv) static int asm9260_wdt_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct asm9260_wdt_priv *priv; struct watchdog_device *wdd; - struct resource *res; int ret; static const char * const mode_name[] = { "hw", "sw", "debug", }; - priv = devm_kzalloc(&pdev->dev, sizeof(struct asm9260_wdt_priv), - GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(struct asm9260_wdt_priv), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->dev = &pdev->dev; + priv->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->iobase = devm_ioremap_resource(&pdev->dev, res); + priv->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->iobase)) return PTR_ERR(priv->iobase); - priv->rst = devm_reset_control_get_exclusive(&pdev->dev, "wdt_rst"); + priv->rst = devm_reset_control_get_exclusive(dev, "wdt_rst"); if (IS_ERR(priv->rst)) return PTR_ERR(priv->rst); @@ -305,7 +314,7 @@ static int asm9260_wdt_probe(struct platform_device *pdev) wdd->ops = &asm9260_wdt_ops; wdd->min_timeout = 1; wdd->max_timeout = BM_WDTC_MAX(priv->wdt_freq); - wdd->parent = &pdev->dev; + wdd->parent = dev; watchdog_set_drvdata(wdd, priv); @@ -315,7 +324,7 @@ static int asm9260_wdt_probe(struct platform_device *pdev) * the max instead. */ wdd->timeout = ASM9260_WDT_DEFAULT_TIMEOUT; - watchdog_init_timeout(wdd, 0, &pdev->dev); + watchdog_init_timeout(wdd, 0, dev); asm9260_wdt_get_dt_mode(priv); @@ -327,49 +336,25 @@ static int asm9260_wdt_probe(struct platform_device *pdev) * Not all supported platforms specify an interrupt for the * watchdog, so let's make it optional. */ - ret = devm_request_irq(&pdev->dev, priv->irq, - asm9260_wdt_irq, 0, pdev->name, priv); + ret = devm_request_irq(dev, priv->irq, asm9260_wdt_irq, 0, + pdev->name, priv); if (ret < 0) - dev_warn(&pdev->dev, "failed to request IRQ\n"); + dev_warn(dev, "failed to request IRQ\n"); } watchdog_set_restart_priority(wdd, 128); - ret = watchdog_register_device(wdd); + watchdog_stop_on_reboot(wdd); + watchdog_stop_on_unregister(wdd); + ret = devm_watchdog_register_device(dev, wdd); if (ret) - goto clk_off; + return ret; platform_set_drvdata(pdev, priv); - dev_info(&pdev->dev, "Watchdog enabled (timeout: %d sec, mode: %s)\n", + dev_info(dev, "Watchdog enabled (timeout: %d sec, mode: %s)\n", wdd->timeout, mode_name[priv->mode]); return 0; - -clk_off: - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); - return ret; -} - -static void asm9260_wdt_shutdown(struct platform_device *pdev) -{ - struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); - - asm9260_wdt_disable(&priv->wdd); -} - -static int asm9260_wdt_remove(struct platform_device *pdev) -{ - struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); - - asm9260_wdt_disable(&priv->wdd); - - watchdog_unregister_device(&priv->wdd); - - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_ahb); - - return 0; } static const struct of_device_id asm9260_wdt_of_match[] = { @@ -384,8 +369,6 @@ static struct platform_driver asm9260_wdt_driver = { .of_match_table = asm9260_wdt_of_match, }, .probe = asm9260_wdt_probe, - .remove = asm9260_wdt_remove, - .shutdown = asm9260_wdt_shutdown, }; module_platform_driver(asm9260_wdt_driver); |