| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * drivers/char/watchdog/pnx4008_wdt.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 11 | 12 | * 2005-2006 (c) MontaVista Software, Inc. |
|---|
| 12 | 13 | * |
|---|
| 13 | 14 | * (C) 2012 Wolfram Sang, Pengutronix |
|---|
| 14 | | - * |
|---|
| 15 | | - * This file is licensed under the terms of the GNU General Public License |
|---|
| 16 | | - * version 2. This program is licensed "as is" without any warranty of any |
|---|
| 17 | | - * kind, whether express or implied. |
|---|
| 18 | 15 | */ |
|---|
| 19 | 16 | |
|---|
| 20 | 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 33 | 30 | #include <linux/of.h> |
|---|
| 34 | 31 | #include <linux/delay.h> |
|---|
| 35 | 32 | #include <linux/reboot.h> |
|---|
| 36 | | -#include <mach/hardware.h> |
|---|
| 37 | 33 | |
|---|
| 38 | 34 | /* WatchDog Timer - Chapter 23 Page 207 */ |
|---|
| 39 | 35 | |
|---|
| .. | .. |
|---|
| 183 | 179 | .max_timeout = MAX_HEARTBEAT, |
|---|
| 184 | 180 | }; |
|---|
| 185 | 181 | |
|---|
| 182 | +static void pnx4008_clk_disable_unprepare(void *data) |
|---|
| 183 | +{ |
|---|
| 184 | + clk_disable_unprepare(data); |
|---|
| 185 | +} |
|---|
| 186 | + |
|---|
| 186 | 187 | static int pnx4008_wdt_probe(struct platform_device *pdev) |
|---|
| 187 | 188 | { |
|---|
| 188 | | - struct resource *r; |
|---|
| 189 | + struct device *dev = &pdev->dev; |
|---|
| 189 | 190 | int ret = 0; |
|---|
| 190 | 191 | |
|---|
| 191 | | - watchdog_init_timeout(&pnx4008_wdd, heartbeat, &pdev->dev); |
|---|
| 192 | + watchdog_init_timeout(&pnx4008_wdd, heartbeat, dev); |
|---|
| 192 | 193 | |
|---|
| 193 | | - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 194 | | - wdt_base = devm_ioremap_resource(&pdev->dev, r); |
|---|
| 194 | + wdt_base = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 195 | 195 | if (IS_ERR(wdt_base)) |
|---|
| 196 | 196 | return PTR_ERR(wdt_base); |
|---|
| 197 | 197 | |
|---|
| 198 | | - wdt_clk = devm_clk_get(&pdev->dev, NULL); |
|---|
| 198 | + wdt_clk = devm_clk_get(dev, NULL); |
|---|
| 199 | 199 | if (IS_ERR(wdt_clk)) |
|---|
| 200 | 200 | return PTR_ERR(wdt_clk); |
|---|
| 201 | 201 | |
|---|
| 202 | 202 | ret = clk_prepare_enable(wdt_clk); |
|---|
| 203 | 203 | if (ret) |
|---|
| 204 | 204 | return ret; |
|---|
| 205 | + ret = devm_add_action_or_reset(dev, pnx4008_clk_disable_unprepare, |
|---|
| 206 | + wdt_clk); |
|---|
| 207 | + if (ret) |
|---|
| 208 | + return ret; |
|---|
| 205 | 209 | |
|---|
| 206 | 210 | pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? |
|---|
| 207 | 211 | WDIOF_CARDRESET : 0; |
|---|
| 208 | | - pnx4008_wdd.parent = &pdev->dev; |
|---|
| 212 | + pnx4008_wdd.parent = dev; |
|---|
| 209 | 213 | watchdog_set_nowayout(&pnx4008_wdd, nowayout); |
|---|
| 210 | 214 | watchdog_set_restart_priority(&pnx4008_wdd, 128); |
|---|
| 211 | 215 | |
|---|
| 212 | | - pnx4008_wdt_stop(&pnx4008_wdd); /* disable for now */ |
|---|
| 216 | + if (readl(WDTIM_CTRL(wdt_base)) & COUNT_ENAB) |
|---|
| 217 | + set_bit(WDOG_HW_RUNNING, &pnx4008_wdd.status); |
|---|
| 213 | 218 | |
|---|
| 214 | | - ret = watchdog_register_device(&pnx4008_wdd); |
|---|
| 215 | | - if (ret < 0) { |
|---|
| 216 | | - dev_err(&pdev->dev, "cannot register watchdog device\n"); |
|---|
| 217 | | - goto disable_clk; |
|---|
| 218 | | - } |
|---|
| 219 | + ret = devm_watchdog_register_device(dev, &pnx4008_wdd); |
|---|
| 220 | + if (ret < 0) |
|---|
| 221 | + return ret; |
|---|
| 219 | 222 | |
|---|
| 220 | | - dev_info(&pdev->dev, "heartbeat %d sec\n", pnx4008_wdd.timeout); |
|---|
| 221 | | - |
|---|
| 222 | | - return 0; |
|---|
| 223 | | - |
|---|
| 224 | | -disable_clk: |
|---|
| 225 | | - clk_disable_unprepare(wdt_clk); |
|---|
| 226 | | - return ret; |
|---|
| 227 | | -} |
|---|
| 228 | | - |
|---|
| 229 | | -static int pnx4008_wdt_remove(struct platform_device *pdev) |
|---|
| 230 | | -{ |
|---|
| 231 | | - watchdog_unregister_device(&pnx4008_wdd); |
|---|
| 232 | | - |
|---|
| 233 | | - clk_disable_unprepare(wdt_clk); |
|---|
| 223 | + dev_info(dev, "heartbeat %d sec\n", pnx4008_wdd.timeout); |
|---|
| 234 | 224 | |
|---|
| 235 | 225 | return 0; |
|---|
| 236 | 226 | } |
|---|
| .. | .. |
|---|
| 249 | 239 | .of_match_table = of_match_ptr(pnx4008_wdt_match), |
|---|
| 250 | 240 | }, |
|---|
| 251 | 241 | .probe = pnx4008_wdt_probe, |
|---|
| 252 | | - .remove = pnx4008_wdt_remove, |
|---|
| 253 | 242 | }; |
|---|
| 254 | 243 | |
|---|
| 255 | 244 | module_platform_driver(platform_wdt_driver); |
|---|