diff options
Diffstat (limited to 'drivers/watchdog/s3c2410_wdt.c')
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 132 |
1 files changed, 39 insertions, 93 deletions
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 200ba236a72e..95416a9bdd4b 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -308,11 +308,6 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt) / S3C2410_WTCON_MAXDIV); } -static inline struct s3c2410_wdt *freq_to_wdt(struct notifier_block *nb) -{ - return container_of(nb, struct s3c2410_wdt, freq_transition); -} - static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask) { const u32 mask_val = BIT(wdt->drv_data->mask_bit); @@ -443,11 +438,6 @@ static int s3c2410wdt_start(struct watchdog_device *wdd) return 0; } -static inline int s3c2410wdt_is_running(struct s3c2410_wdt *wdt) -{ - return readl(wdt->reg_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE; -} - static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd, unsigned int timeout) { @@ -579,8 +569,8 @@ static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt) return 0; } -static inline const struct s3c2410_wdt_variant * -s3c2410_get_wdt_drv_data(struct platform_device *pdev) +static inline int +s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt) { const struct s3c2410_wdt_variant *variant; struct device *dev = &pdev->dev; @@ -601,26 +591,30 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev) err = of_property_read_u32(dev->of_node, "samsung,cluster-index", &index); - if (err) { - dev_err(dev, "failed to get cluster index\n"); - return NULL; - } + if (err) + return dev_err_probe(dev, -EINVAL, "failed to get cluster index\n"); switch (index) { case 0: - return variant; + break; case 1: - return (variant == &drv_data_exynos850_cl0) ? + variant = (variant == &drv_data_exynos850_cl0) ? &drv_data_exynos850_cl1 : &drv_data_exynosautov9_cl1; + break; default: - dev_err(dev, "wrong cluster index: %u\n", index); - return NULL; + return dev_err_probe(dev, -EINVAL, "wrong cluster index: %u\n", index); } } #endif - return variant; + wdt->drv_data = variant; + return 0; +} + +static void s3c2410wdt_wdt_disable_action(void *data) +{ + s3c2410wdt_enable(data, false); } static int s3c2410wdt_probe(struct platform_device *pdev) @@ -639,17 +633,16 @@ static int s3c2410wdt_probe(struct platform_device *pdev) spin_lock_init(&wdt->lock); wdt->wdt_device = s3c2410_wdd; - wdt->drv_data = s3c2410_get_wdt_drv_data(pdev); - if (!wdt->drv_data) - return -EINVAL; + ret = s3c2410_get_wdt_drv_data(pdev, wdt); + if (ret) + return ret; if (wdt->drv_data->quirks & QUIRKS_HAVE_PMUREG) { wdt->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node, "samsung,syscon-phandle"); - if (IS_ERR(wdt->pmureg)) { - dev_err(dev, "syscon regmap lookup failed.\n"); - return PTR_ERR(wdt->pmureg); - } + if (IS_ERR(wdt->pmureg)) + return dev_err_probe(dev, PTR_ERR(wdt->pmureg), + "syscon regmap lookup failed.\n"); } wdt_irq = platform_get_irq(pdev, 0); @@ -661,35 +654,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt->reg_base)) return PTR_ERR(wdt->reg_base); - wdt->bus_clk = devm_clk_get(dev, "watchdog"); - if (IS_ERR(wdt->bus_clk)) { - dev_err(dev, "failed to find bus clock\n"); - return PTR_ERR(wdt->bus_clk); - } - - ret = clk_prepare_enable(wdt->bus_clk); - if (ret < 0) { - dev_err(dev, "failed to enable bus clock\n"); - return ret; - } + wdt->bus_clk = devm_clk_get_enabled(dev, "watchdog"); + if (IS_ERR(wdt->bus_clk)) + return dev_err_probe(dev, PTR_ERR(wdt->bus_clk), "failed to get bus clock\n"); /* * "watchdog_src" clock is optional; if it's not present -- just skip it * and use "watchdog" clock as both bus and source clock. */ - wdt->src_clk = devm_clk_get_optional(dev, "watchdog_src"); - if (IS_ERR(wdt->src_clk)) { - dev_err_probe(dev, PTR_ERR(wdt->src_clk), - "failed to get source clock\n"); - ret = PTR_ERR(wdt->src_clk); - goto err_bus_clk; - } - - ret = clk_prepare_enable(wdt->src_clk); - if (ret) { - dev_err(dev, "failed to enable source clock\n"); - goto err_bus_clk; - } + wdt->src_clk = devm_clk_get_optional_enabled(dev, "watchdog_src"); + if (IS_ERR(wdt->src_clk)) + return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n"); wdt->wdt_device.min_timeout = 1; wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt); @@ -705,21 +680,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev) if (ret) { ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device, S3C2410_WATCHDOG_DEFAULT_TIME); - if (ret == 0) { + if (ret == 0) dev_warn(dev, "tmr_margin value out of range, default %d used\n", S3C2410_WATCHDOG_DEFAULT_TIME); - } else { - dev_err(dev, "failed to use default timeout\n"); - goto err_src_clk; - } + else + return dev_err_probe(dev, ret, "failed to use default timeout\n"); } ret = devm_request_irq(dev, wdt_irq, s3c2410wdt_irq, 0, pdev->name, pdev); - if (ret != 0) { - dev_err(dev, "failed to install irq (%d)\n", ret); - goto err_src_clk; - } + if (ret != 0) + return dev_err_probe(dev, ret, "failed to install irq (%d)\n", ret); watchdog_set_nowayout(&wdt->wdt_device, nowayout); watchdog_set_restart_priority(&wdt->wdt_device, 128); @@ -742,13 +713,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev) s3c2410wdt_stop(&wdt->wdt_device); } - ret = watchdog_register_device(&wdt->wdt_device); + ret = devm_watchdog_register_device(dev, &wdt->wdt_device); if (ret) - goto err_src_clk; + return ret; ret = s3c2410wdt_enable(wdt, true); if (ret < 0) - goto err_unregister; + return ret; + + ret = devm_add_action_or_reset(dev, s3c2410wdt_wdt_disable_action, wdt); + if (ret) + return ret; platform_set_drvdata(pdev, wdt); @@ -762,34 +737,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev) (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis"); return 0; - - err_unregister: - watchdog_unregister_device(&wdt->wdt_device); - - err_src_clk: - clk_disable_unprepare(wdt->src_clk); - - err_bus_clk: - clk_disable_unprepare(wdt->bus_clk); - - return ret; -} - -static int s3c2410wdt_remove(struct platform_device *dev) -{ - int ret; - struct s3c2410_wdt *wdt = platform_get_drvdata(dev); - - ret = s3c2410wdt_enable(wdt, false); - if (ret < 0) - return ret; - - watchdog_unregister_device(&wdt->wdt_device); - - clk_disable_unprepare(wdt->src_clk); - clk_disable_unprepare(wdt->bus_clk); - - return 0; } static void s3c2410wdt_shutdown(struct platform_device *dev) @@ -844,7 +791,6 @@ static DEFINE_SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops, static struct platform_driver s3c2410wdt_driver = { .probe = s3c2410wdt_probe, - .remove = s3c2410wdt_remove, .shutdown = s3c2410wdt_shutdown, .id_table = s3c2410_wdt_ids, .driver = { |