diff options
Diffstat (limited to 'drivers/watchdog/st_lpc_wdt.c')
| -rw-r--r-- | drivers/watchdog/st_lpc_wdt.c | 75 |
1 files changed, 31 insertions, 44 deletions
diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c index 177829b379da..d206452072ae 100644 --- a/drivers/watchdog/st_lpc_wdt.c +++ b/drivers/watchdog/st_lpc_wdt.c @@ -15,7 +15,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/watchdog.h> @@ -42,7 +41,7 @@ struct st_wdog { void __iomem *base; struct device *dev; struct regmap *regmap; - struct st_wdog_syscfg *syscfg; + const struct st_wdog_syscfg *syscfg; struct clk *clk; unsigned long clkrate; bool warm_reset; @@ -142,13 +141,17 @@ static struct watchdog_device st_wdog_dev = { .ops = &st_wdog_ops, }; +static void st_clk_disable_unprepare(void *data) +{ + clk_disable_unprepare(data); +} + static int st_wdog_probe(struct platform_device *pdev) { - const struct of_device_id *match; - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct st_wdog *st_wdog; struct regmap *regmap; - struct resource *res; struct clk *clk; void __iomem *base; uint32_t mode; @@ -156,7 +159,7 @@ static int st_wdog_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "st,lpc-mode", &mode); if (ret) { - dev_err(&pdev->dev, "An LPC mode must be provided\n"); + dev_err(dev, "An LPC mode must be provided\n"); return -EINVAL; } @@ -164,35 +167,29 @@ static int st_wdog_probe(struct platform_device *pdev) if (mode != ST_LPC_MODE_WDT) return -ENODEV; - st_wdog = devm_kzalloc(&pdev->dev, sizeof(*st_wdog), GFP_KERNEL); + st_wdog = devm_kzalloc(dev, sizeof(*st_wdog), GFP_KERNEL); if (!st_wdog) return -ENOMEM; - match = of_match_device(st_wdog_match, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "Couldn't match device\n"); - return -ENODEV; - } - st_wdog->syscfg = (struct st_wdog_syscfg *)match->data; + st_wdog->syscfg = (struct st_wdog_syscfg *)device_get_match_data(dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); if (IS_ERR(regmap)) { - dev_err(&pdev->dev, "No syscfg phandle specified\n"); + dev_err(dev, "No syscfg phandle specified\n"); return PTR_ERR(regmap); } - clk = devm_clk_get(&pdev->dev, NULL); + clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { - dev_err(&pdev->dev, "Unable to request clock\n"); + dev_err(dev, "Unable to request clock\n"); return PTR_ERR(clk); } - st_wdog->dev = &pdev->dev; + st_wdog->dev = dev; st_wdog->base = base; st_wdog->clk = clk; st_wdog->regmap = regmap; @@ -200,56 +197,48 @@ static int st_wdog_probe(struct platform_device *pdev) st_wdog->clkrate = clk_get_rate(st_wdog->clk); if (!st_wdog->clkrate) { - dev_err(&pdev->dev, "Unable to fetch clock rate\n"); + dev_err(dev, "Unable to fetch clock rate\n"); return -EINVAL; } st_wdog_dev.max_timeout = 0xFFFFFFFF / st_wdog->clkrate; - st_wdog_dev.parent = &pdev->dev; + st_wdog_dev.parent = dev; ret = clk_prepare_enable(clk); if (ret) { - dev_err(&pdev->dev, "Unable to enable clock\n"); + dev_err(dev, "Unable to enable clock\n"); return ret; } + ret = devm_add_action_or_reset(dev, st_clk_disable_unprepare, clk); + if (ret) + return ret; watchdog_set_drvdata(&st_wdog_dev, st_wdog); watchdog_set_nowayout(&st_wdog_dev, WATCHDOG_NOWAYOUT); /* Init Watchdog timeout with value in DT */ - ret = watchdog_init_timeout(&st_wdog_dev, 0, &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "Unable to initialise watchdog timeout\n"); - clk_disable_unprepare(clk); + ret = watchdog_init_timeout(&st_wdog_dev, 0, dev); + if (ret) return ret; - } - ret = watchdog_register_device(&st_wdog_dev); - if (ret) { - dev_err(&pdev->dev, "Unable to register watchdog\n"); - clk_disable_unprepare(clk); + ret = devm_watchdog_register_device(dev, &st_wdog_dev); + if (ret) return ret; - } st_wdog_setup(st_wdog, true); - dev_info(&pdev->dev, "LPC Watchdog driver registered, reset type is %s", + dev_info(dev, "LPC Watchdog driver registered, reset type is %s", st_wdog->warm_reset ? "warm" : "cold"); return ret; } -static int st_wdog_remove(struct platform_device *pdev) +static void st_wdog_remove(struct platform_device *pdev) { struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev); st_wdog_setup(st_wdog, false); - watchdog_unregister_device(&st_wdog_dev); - clk_disable_unprepare(st_wdog->clk); - - return 0; } -#ifdef CONFIG_PM_SLEEP static int st_wdog_suspend(struct device *dev) { struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev); @@ -286,16 +275,14 @@ static int st_wdog_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(st_wdog_pm_ops, - st_wdog_suspend, - st_wdog_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(st_wdog_pm_ops, + st_wdog_suspend, st_wdog_resume); static struct platform_driver st_wdog_driver = { .driver = { .name = "st-lpc-wdt", - .pm = &st_wdog_pm_ops, + .pm = pm_sleep_ptr(&st_wdog_pm_ops), .of_match_table = st_wdog_match, }, .probe = st_wdog_probe, |
