.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * watchdog driver for ZTE's zx2967 family |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2017 ZTE Ltd. |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Baoyou Xie <baoyou.xie@linaro.org> |
---|
7 | | - * |
---|
8 | | - * License terms: GNU General Public License (GPL) version 2 |
---|
9 | 8 | */ |
---|
10 | 9 | |
---|
11 | 10 | #include <linux/clk.h> |
---|
.. | .. |
---|
188 | 187 | of_node_put(out_args.np); |
---|
189 | 188 | } |
---|
190 | 189 | |
---|
| 190 | +static void zx2967_clk_disable_unprepare(void *data) |
---|
| 191 | +{ |
---|
| 192 | + clk_disable_unprepare(data); |
---|
| 193 | +} |
---|
| 194 | + |
---|
191 | 195 | static int zx2967_wdt_probe(struct platform_device *pdev) |
---|
192 | 196 | { |
---|
193 | 197 | struct device *dev = &pdev->dev; |
---|
194 | 198 | struct zx2967_wdt *wdt; |
---|
195 | | - struct resource *base; |
---|
196 | 199 | int ret; |
---|
197 | 200 | struct reset_control *rstc; |
---|
198 | 201 | |
---|
.. | .. |
---|
207 | 210 | wdt->wdt_device.timeout = ZX2967_WDT_DEFAULT_TIMEOUT; |
---|
208 | 211 | wdt->wdt_device.max_timeout = ZX2967_WDT_MAX_TIMEOUT; |
---|
209 | 212 | wdt->wdt_device.min_timeout = ZX2967_WDT_MIN_TIMEOUT; |
---|
210 | | - wdt->wdt_device.parent = &pdev->dev; |
---|
| 213 | + wdt->wdt_device.parent = dev; |
---|
211 | 214 | |
---|
212 | | - base = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
213 | | - wdt->reg_base = devm_ioremap_resource(dev, base); |
---|
| 215 | + wdt->reg_base = devm_platform_ioremap_resource(pdev, 0); |
---|
214 | 216 | if (IS_ERR(wdt->reg_base)) |
---|
215 | 217 | return PTR_ERR(wdt->reg_base); |
---|
216 | 218 | |
---|
.. | .. |
---|
227 | 229 | dev_err(dev, "failed to enable clock\n"); |
---|
228 | 230 | return ret; |
---|
229 | 231 | } |
---|
| 232 | + ret = devm_add_action_or_reset(dev, zx2967_clk_disable_unprepare, |
---|
| 233 | + wdt->clock); |
---|
| 234 | + if (ret) |
---|
| 235 | + return ret; |
---|
230 | 236 | clk_set_rate(wdt->clock, ZX2967_WDT_CLK_FREQ); |
---|
231 | 237 | |
---|
232 | 238 | rstc = devm_reset_control_get_exclusive(dev, NULL); |
---|
233 | 239 | if (IS_ERR(rstc)) { |
---|
234 | 240 | dev_err(dev, "failed to get rstc"); |
---|
235 | | - ret = PTR_ERR(rstc); |
---|
236 | | - goto err; |
---|
| 241 | + return PTR_ERR(rstc); |
---|
237 | 242 | } |
---|
238 | 243 | |
---|
239 | 244 | reset_control_assert(rstc); |
---|
.. | .. |
---|
244 | 249 | ZX2967_WDT_DEFAULT_TIMEOUT, dev); |
---|
245 | 250 | watchdog_set_nowayout(&wdt->wdt_device, WATCHDOG_NOWAYOUT); |
---|
246 | 251 | |
---|
247 | | - ret = watchdog_register_device(&wdt->wdt_device); |
---|
| 252 | + ret = devm_watchdog_register_device(dev, &wdt->wdt_device); |
---|
248 | 253 | if (ret) |
---|
249 | | - goto err; |
---|
| 254 | + return ret; |
---|
250 | 255 | |
---|
251 | 256 | dev_info(dev, "watchdog enabled (timeout=%d sec, nowayout=%d)", |
---|
252 | 257 | wdt->wdt_device.timeout, WATCHDOG_NOWAYOUT); |
---|
253 | | - |
---|
254 | | - return 0; |
---|
255 | | - |
---|
256 | | -err: |
---|
257 | | - clk_disable_unprepare(wdt->clock); |
---|
258 | | - return ret; |
---|
259 | | -} |
---|
260 | | - |
---|
261 | | -static int zx2967_wdt_remove(struct platform_device *pdev) |
---|
262 | | -{ |
---|
263 | | - struct zx2967_wdt *wdt = platform_get_drvdata(pdev); |
---|
264 | | - |
---|
265 | | - watchdog_unregister_device(&wdt->wdt_device); |
---|
266 | | - clk_disable_unprepare(wdt->clock); |
---|
267 | 258 | |
---|
268 | 259 | return 0; |
---|
269 | 260 | } |
---|
.. | .. |
---|
276 | 267 | |
---|
277 | 268 | static struct platform_driver zx2967_wdt_driver = { |
---|
278 | 269 | .probe = zx2967_wdt_probe, |
---|
279 | | - .remove = zx2967_wdt_remove, |
---|
280 | 270 | .driver = { |
---|
281 | 271 | .name = "zx2967-wdt", |
---|
282 | 272 | .of_match_table = of_match_ptr(zx2967_wdt_match), |
---|