27
27
#include <linux/module.h>
28
28
#include <linux/moduleparam.h>
29
29
#include <linux/of_address.h>
30
+ #include <linux/of_device.h>
30
31
#include <linux/platform_device.h>
31
32
#include <linux/regmap.h>
32
33
#include <linux/watchdog.h>
35
36
36
37
#define IMX2_WDT_WCR 0x00 /* Control Register */
37
38
#define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */
39
+ #define IMX2_WDT_WCR_WDW BIT(7) /* -> Watchdog disable for WAIT */
38
40
#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
39
41
#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
40
42
#define IMX2_WDT_WCR_WRE BIT(3) /* -> WDOG Reset Enable */
60
62
61
63
#define WDOG_SEC_TO_COUNT (s ) ((s * 2 - 1) << 8)
62
64
65
+ struct imx2_wdt_data {
66
+ bool wdw_supported ;
67
+ };
68
+
63
69
struct imx2_wdt_device {
64
70
struct clk * clk ;
65
71
struct regmap * regmap ;
66
72
struct watchdog_device wdog ;
73
+ const struct imx2_wdt_data * data ;
67
74
bool ext_reset ;
68
75
bool clk_is_on ;
69
76
bool no_ping ;
77
+ bool sleep_wait ;
70
78
};
71
79
72
80
static bool nowayout = WATCHDOG_NOWAYOUT ;
@@ -129,6 +137,9 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog)
129
137
130
138
/* Suspend timer in low power mode, write once-only */
131
139
val |= IMX2_WDT_WCR_WDZST ;
140
+ /* Suspend timer in low power WAIT mode, write once-only */
141
+ if (wdev -> sleep_wait )
142
+ val |= IMX2_WDT_WCR_WDW ;
132
143
/* Strip the old watchdog Time-Out value */
133
144
val &= ~IMX2_WDT_WCR_WT ;
134
145
/* Generate internal chip-level reset if WDOG times out */
@@ -292,6 +303,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
292
303
wdog -> max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000 ;
293
304
wdog -> parent = dev ;
294
305
306
+ wdev -> data = of_device_get_match_data (dev );
307
+
295
308
ret = platform_get_irq (pdev , 0 );
296
309
if (ret > 0 )
297
310
if (!devm_request_irq (dev , ret , imx2_wdt_isr , 0 ,
@@ -313,9 +326,18 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
313
326
314
327
wdev -> ext_reset = of_property_read_bool (dev -> of_node ,
315
328
"fsl,ext-reset-output" );
329
+
330
+ if (of_property_read_bool (dev -> of_node , "fsl,suspend-in-wait" )) {
331
+ if (!wdev -> data -> wdw_supported ) {
332
+ dev_err (dev , "suspend-in-wait not supported\n" );
333
+ return - EINVAL ;
334
+ }
335
+ wdev -> sleep_wait = true;
336
+ }
337
+
316
338
/*
317
339
* The i.MX7D doesn't support low power mode, so we need to ping the watchdog
318
- * during suspend.
340
+ * during suspend. Interaction with "fsl,suspend-in-wait" is unknown!
319
341
*/
320
342
wdev -> no_ping = !of_device_is_compatible (dev -> of_node , "fsl,imx7d-wdt" );
321
343
platform_set_drvdata (pdev , wdog );
@@ -417,9 +439,36 @@ static int __maybe_unused imx2_wdt_resume(struct device *dev)
417
439
static SIMPLE_DEV_PM_OPS (imx2_wdt_pm_ops , imx2_wdt_suspend ,
418
440
imx2_wdt_resume ) ;
419
441
442
+ struct imx2_wdt_data imx_wdt = {
443
+ .wdw_supported = true,
444
+ };
445
+
446
+ struct imx2_wdt_data imx_wdt_legacy = {
447
+ .wdw_supported = false,
448
+ };
449
+
420
450
static const struct of_device_id imx2_wdt_dt_ids [] = {
421
- { .compatible = "fsl,imx21-wdt" , },
422
- { .compatible = "fsl,imx7d-wdt" , },
451
+ { .compatible = "fsl,imx21-wdt" , .data = & imx_wdt_legacy },
452
+ { .compatible = "fsl,imx25-wdt" , .data = & imx_wdt },
453
+ { .compatible = "fsl,imx27-wdt" , .data = & imx_wdt_legacy },
454
+ { .compatible = "fsl,imx31-wdt" , .data = & imx_wdt_legacy },
455
+ { .compatible = "fsl,imx35-wdt" , .data = & imx_wdt },
456
+ { .compatible = "fsl,imx50-wdt" , .data = & imx_wdt },
457
+ { .compatible = "fsl,imx51-wdt" , .data = & imx_wdt },
458
+ { .compatible = "fsl,imx53-wdt" , .data = & imx_wdt },
459
+ { .compatible = "fsl,imx6q-wdt" , .data = & imx_wdt },
460
+ { .compatible = "fsl,imx6sl-wdt" , .data = & imx_wdt },
461
+ { .compatible = "fsl,imx6sll-wdt" , .data = & imx_wdt },
462
+ { .compatible = "fsl,imx6sx-wdt" , .data = & imx_wdt },
463
+ { .compatible = "fsl,imx6ul-wdt" , .data = & imx_wdt },
464
+ { .compatible = "fsl,imx7d-wdt" , .data = & imx_wdt },
465
+ { .compatible = "fsl,imx8mm-wdt" , .data = & imx_wdt },
466
+ { .compatible = "fsl,imx8mn-wdt" , .data = & imx_wdt },
467
+ { .compatible = "fsl,imx8mp-wdt" , .data = & imx_wdt },
468
+ { .compatible = "fsl,imx8mq-wdt" , .data = & imx_wdt },
469
+ { .compatible = "fsl,ls1012a-wdt" , .data = & imx_wdt_legacy },
470
+ { .compatible = "fsl,ls1043a-wdt" , .data = & imx_wdt_legacy },
471
+ { .compatible = "fsl,vf610-wdt" , .data = & imx_wdt },
423
472
{ /* sentinel */ }
424
473
};
425
474
MODULE_DEVICE_TABLE (of , imx2_wdt_dt_ids );
0 commit comments