11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
280e45b1eSTimo Kokkonen /*
380e45b1eSTimo Kokkonen * Copyright (C) Nokia Corporation
480e45b1eSTimo Kokkonen *
580e45b1eSTimo Kokkonen * Written by Timo Kokkonen <timo.t.kokkonen at nokia.com>
680e45b1eSTimo Kokkonen */
780e45b1eSTimo Kokkonen
880e45b1eSTimo Kokkonen #include <linux/module.h>
980e45b1eSTimo Kokkonen #include <linux/types.h>
105a0e3ad6STejun Heo #include <linux/slab.h>
1180e45b1eSTimo Kokkonen #include <linux/kernel.h>
12099d387eSDmitry Torokhov #include <linux/mod_devicetable.h>
1380e45b1eSTimo Kokkonen #include <linux/watchdog.h>
1480e45b1eSTimo Kokkonen #include <linux/platform_device.h>
15a2054256SWolfram Sang #include <linux/mfd/twl.h>
1680e45b1eSTimo Kokkonen
1780e45b1eSTimo Kokkonen #define TWL4030_WATCHDOG_CFG_REG_OFFS 0x3
1880e45b1eSTimo Kokkonen
1986a1e189SWim Van Sebroeck static bool nowayout = WATCHDOG_NOWAYOUT;
2086a1e189SWim Van Sebroeck module_param(nowayout, bool, 0);
2180e45b1eSTimo Kokkonen MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
2280e45b1eSTimo Kokkonen "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
2380e45b1eSTimo Kokkonen
twl4030_wdt_write(unsigned char val)2480e45b1eSTimo Kokkonen static int twl4030_wdt_write(unsigned char val)
2580e45b1eSTimo Kokkonen {
262bc3f62fSPeter Ujfalusi return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, val,
2780e45b1eSTimo Kokkonen TWL4030_WATCHDOG_CFG_REG_OFFS);
2880e45b1eSTimo Kokkonen }
2980e45b1eSTimo Kokkonen
twl4030_wdt_start(struct watchdog_device * wdt)30b2c4e4b2SJarkko Nikula static int twl4030_wdt_start(struct watchdog_device *wdt)
3180e45b1eSTimo Kokkonen {
32b2c4e4b2SJarkko Nikula return twl4030_wdt_write(wdt->timeout + 1);
3380e45b1eSTimo Kokkonen }
3480e45b1eSTimo Kokkonen
twl4030_wdt_stop(struct watchdog_device * wdt)35b2c4e4b2SJarkko Nikula static int twl4030_wdt_stop(struct watchdog_device *wdt)
3680e45b1eSTimo Kokkonen {
3780e45b1eSTimo Kokkonen return twl4030_wdt_write(0);
3880e45b1eSTimo Kokkonen }
3980e45b1eSTimo Kokkonen
twl4030_wdt_set_timeout(struct watchdog_device * wdt,unsigned int timeout)40b2c4e4b2SJarkko Nikula static int twl4030_wdt_set_timeout(struct watchdog_device *wdt,
41b2c4e4b2SJarkko Nikula unsigned int timeout)
4280e45b1eSTimo Kokkonen {
43b2c4e4b2SJarkko Nikula wdt->timeout = timeout;
44b2c4e4b2SJarkko Nikula return 0;
4580e45b1eSTimo Kokkonen }
4680e45b1eSTimo Kokkonen
47b2c4e4b2SJarkko Nikula static const struct watchdog_info twl4030_wdt_info = {
48fb1cbeaeSTony Lindgren .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
4980e45b1eSTimo Kokkonen .identity = "TWL4030 Watchdog",
5080e45b1eSTimo Kokkonen };
5180e45b1eSTimo Kokkonen
52b2c4e4b2SJarkko Nikula static const struct watchdog_ops twl4030_wdt_ops = {
5380e45b1eSTimo Kokkonen .owner = THIS_MODULE,
54b2c4e4b2SJarkko Nikula .start = twl4030_wdt_start,
55b2c4e4b2SJarkko Nikula .stop = twl4030_wdt_stop,
56b2c4e4b2SJarkko Nikula .set_timeout = twl4030_wdt_set_timeout,
5780e45b1eSTimo Kokkonen };
5880e45b1eSTimo Kokkonen
twl4030_wdt_probe(struct platform_device * pdev)592d991a16SBill Pemberton static int twl4030_wdt_probe(struct platform_device *pdev)
6080e45b1eSTimo Kokkonen {
61b42488bcSGuenter Roeck struct device *dev = &pdev->dev;
62b2c4e4b2SJarkko Nikula struct watchdog_device *wdt;
6380e45b1eSTimo Kokkonen
64b42488bcSGuenter Roeck wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
6580e45b1eSTimo Kokkonen if (!wdt)
6680e45b1eSTimo Kokkonen return -ENOMEM;
6780e45b1eSTimo Kokkonen
68b2c4e4b2SJarkko Nikula wdt->info = &twl4030_wdt_info;
69b2c4e4b2SJarkko Nikula wdt->ops = &twl4030_wdt_ops;
70b2c4e4b2SJarkko Nikula wdt->status = 0;
71b2c4e4b2SJarkko Nikula wdt->timeout = 30;
72b2c4e4b2SJarkko Nikula wdt->min_timeout = 1;
73b2c4e4b2SJarkko Nikula wdt->max_timeout = 30;
74b42488bcSGuenter Roeck wdt->parent = dev;
7580e45b1eSTimo Kokkonen
76b2c4e4b2SJarkko Nikula watchdog_set_nowayout(wdt, nowayout);
7780e45b1eSTimo Kokkonen platform_set_drvdata(pdev, wdt);
7880e45b1eSTimo Kokkonen
79b2c4e4b2SJarkko Nikula twl4030_wdt_stop(wdt);
8080e45b1eSTimo Kokkonen
81b42488bcSGuenter Roeck return devm_watchdog_register_device(dev, wdt);
8280e45b1eSTimo Kokkonen }
8380e45b1eSTimo Kokkonen
twl4030_wdt_suspend(struct platform_device * pdev,pm_message_t state)8480e45b1eSTimo Kokkonen static int twl4030_wdt_suspend(struct platform_device *pdev, pm_message_t state)
8580e45b1eSTimo Kokkonen {
86b2c4e4b2SJarkko Nikula struct watchdog_device *wdt = platform_get_drvdata(pdev);
87b2c4e4b2SJarkko Nikula if (watchdog_active(wdt))
88b2c4e4b2SJarkko Nikula return twl4030_wdt_stop(wdt);
8980e45b1eSTimo Kokkonen
9080e45b1eSTimo Kokkonen return 0;
9180e45b1eSTimo Kokkonen }
9280e45b1eSTimo Kokkonen
twl4030_wdt_resume(struct platform_device * pdev)9380e45b1eSTimo Kokkonen static int twl4030_wdt_resume(struct platform_device *pdev)
9480e45b1eSTimo Kokkonen {
95b2c4e4b2SJarkko Nikula struct watchdog_device *wdt = platform_get_drvdata(pdev);
96b2c4e4b2SJarkko Nikula if (watchdog_active(wdt))
97b2c4e4b2SJarkko Nikula return twl4030_wdt_start(wdt);
9880e45b1eSTimo Kokkonen
9980e45b1eSTimo Kokkonen return 0;
10080e45b1eSTimo Kokkonen }
10180e45b1eSTimo Kokkonen
1028899b8d9SAaro Koskinen static const struct of_device_id twl_wdt_of_match[] = {
1038899b8d9SAaro Koskinen { .compatible = "ti,twl4030-wdt", },
1048899b8d9SAaro Koskinen { },
1058899b8d9SAaro Koskinen };
1068899b8d9SAaro Koskinen MODULE_DEVICE_TABLE(of, twl_wdt_of_match);
1078899b8d9SAaro Koskinen
10880e45b1eSTimo Kokkonen static struct platform_driver twl4030_wdt_driver = {
10980e45b1eSTimo Kokkonen .probe = twl4030_wdt_probe,
110*d36eda79SPaul Cercueil .suspend = pm_ptr(twl4030_wdt_suspend),
111*d36eda79SPaul Cercueil .resume = pm_ptr(twl4030_wdt_resume),
11280e45b1eSTimo Kokkonen .driver = {
11380e45b1eSTimo Kokkonen .name = "twl4030_wdt",
1148899b8d9SAaro Koskinen .of_match_table = twl_wdt_of_match,
11580e45b1eSTimo Kokkonen },
11680e45b1eSTimo Kokkonen };
11780e45b1eSTimo Kokkonen
118b8ec6118SAxel Lin module_platform_driver(twl4030_wdt_driver);
11980e45b1eSTimo Kokkonen
12080e45b1eSTimo Kokkonen MODULE_AUTHOR("Nokia Corporation");
12180e45b1eSTimo Kokkonen MODULE_LICENSE("GPL");
12280e45b1eSTimo Kokkonen MODULE_ALIAS("platform:twl4030_wdt");
12380e45b1eSTimo Kokkonen
124