2 * Maxim MAX77620 Watchdog Driver
4 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
6 * Author: Laxman Dewangan <ldewangan@nvidia.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/err.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/mfd/max77620.h>
19 #include <linux/platform_device.h>
20 #include <linux/regmap.h>
21 #include <linux/slab.h>
22 #include <linux/watchdog.h>
24 static bool nowayout
= WATCHDOG_NOWAYOUT
;
29 struct watchdog_device wdt_dev
;
32 static int max77620_wdt_start(struct watchdog_device
*wdt_dev
)
34 struct max77620_wdt
*wdt
= watchdog_get_drvdata(wdt_dev
);
36 return regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL2
,
37 MAX77620_WDTEN
, MAX77620_WDTEN
);
40 static int max77620_wdt_stop(struct watchdog_device
*wdt_dev
)
42 struct max77620_wdt
*wdt
= watchdog_get_drvdata(wdt_dev
);
44 return regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL2
,
48 static int max77620_wdt_ping(struct watchdog_device
*wdt_dev
)
50 struct max77620_wdt
*wdt
= watchdog_get_drvdata(wdt_dev
);
52 return regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL3
,
53 MAX77620_WDTC_MASK
, 0x1);
56 static int max77620_wdt_set_timeout(struct watchdog_device
*wdt_dev
,
59 struct max77620_wdt
*wdt
= watchdog_get_drvdata(wdt_dev
);
60 unsigned int wdt_timeout
;
66 regval
= MAX77620_TWD_2s
;
71 regval
= MAX77620_TWD_16s
;
76 regval
= MAX77620_TWD_64s
;
81 regval
= MAX77620_TWD_128s
;
86 ret
= regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL3
,
87 MAX77620_WDTC_MASK
, 0x1);
91 ret
= regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL2
,
92 MAX77620_TWD_MASK
, regval
);
96 wdt_dev
->timeout
= wdt_timeout
;
101 static const struct watchdog_info max77620_wdt_info
= {
102 .identity
= "max77620-watchdog",
103 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
106 static const struct watchdog_ops max77620_wdt_ops
= {
107 .start
= max77620_wdt_start
,
108 .stop
= max77620_wdt_stop
,
109 .ping
= max77620_wdt_ping
,
110 .set_timeout
= max77620_wdt_set_timeout
,
113 static int max77620_wdt_probe(struct platform_device
*pdev
)
115 struct max77620_wdt
*wdt
;
116 struct watchdog_device
*wdt_dev
;
120 wdt
= devm_kzalloc(&pdev
->dev
, sizeof(*wdt
), GFP_KERNEL
);
124 wdt
->dev
= &pdev
->dev
;
125 wdt
->rmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
127 dev_err(wdt
->dev
, "Failed to get parent regmap\n");
131 wdt_dev
= &wdt
->wdt_dev
;
132 wdt_dev
->info
= &max77620_wdt_info
;
133 wdt_dev
->ops
= &max77620_wdt_ops
;
134 wdt_dev
->min_timeout
= 2;
135 wdt_dev
->max_timeout
= 128;
136 wdt_dev
->max_hw_heartbeat_ms
= 128 * 1000;
138 platform_set_drvdata(pdev
, wdt
);
140 /* Enable WD_RST_WK - WDT expire results in a restart */
141 ret
= regmap_update_bits(wdt
->rmap
, MAX77620_REG_ONOFFCNFG2
,
142 MAX77620_ONOFFCNFG2_WD_RST_WK
,
143 MAX77620_ONOFFCNFG2_WD_RST_WK
);
145 dev_err(wdt
->dev
, "Failed to set WD_RST_WK: %d\n", ret
);
149 /* Set WDT clear in OFF and sleep mode */
150 ret
= regmap_update_bits(wdt
->rmap
, MAX77620_REG_CNFGGLBL2
,
151 MAX77620_WDTOFFC
| MAX77620_WDTSLPC
,
152 MAX77620_WDTOFFC
| MAX77620_WDTSLPC
);
154 dev_err(wdt
->dev
, "Failed to set WDT OFF mode: %d\n", ret
);
158 /* Check if WDT running and if yes then set flags properly */
159 ret
= regmap_read(wdt
->rmap
, MAX77620_REG_CNFGGLBL2
, ®val
);
161 dev_err(wdt
->dev
, "Failed to read WDT CFG register: %d\n", ret
);
165 switch (regval
& MAX77620_TWD_MASK
) {
166 case MAX77620_TWD_2s
:
167 wdt_dev
->timeout
= 2;
169 case MAX77620_TWD_16s
:
170 wdt_dev
->timeout
= 16;
172 case MAX77620_TWD_64s
:
173 wdt_dev
->timeout
= 64;
176 wdt_dev
->timeout
= 128;
180 if (regval
& MAX77620_WDTEN
)
181 set_bit(WDOG_HW_RUNNING
, &wdt_dev
->status
);
183 watchdog_set_nowayout(wdt_dev
, nowayout
);
184 watchdog_set_drvdata(wdt_dev
, wdt
);
186 ret
= watchdog_register_device(wdt_dev
);
188 dev_err(&pdev
->dev
, "watchdog registration failed: %d\n", ret
);
195 static int max77620_wdt_remove(struct platform_device
*pdev
)
197 struct max77620_wdt
*wdt
= platform_get_drvdata(pdev
);
199 max77620_wdt_stop(&wdt
->wdt_dev
);
200 watchdog_unregister_device(&wdt
->wdt_dev
);
205 static const struct platform_device_id max77620_wdt_devtype
[] = {
206 { .name
= "max77620-watchdog", },
209 MODULE_DEVICE_TABLE(platform
, max77620_wdt_devtype
);
211 static struct platform_driver max77620_wdt_driver
= {
213 .name
= "max77620-watchdog",
215 .probe
= max77620_wdt_probe
,
216 .remove
= max77620_wdt_remove
,
217 .id_table
= max77620_wdt_devtype
,
220 module_platform_driver(max77620_wdt_driver
);
222 MODULE_DESCRIPTION("Max77620 watchdog timer driver");
224 module_param(nowayout
, bool, 0);
225 MODULE_PARM_DESC(nowayout
, "Watchdog cannot be stopped once started "
226 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
228 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
229 MODULE_LICENSE("GPL v2");