1*80141041SZi-Yu Chen // SPDX-License-Identifier: GPL-2.0-only 2*80141041SZi-Yu Chen /* 3*80141041SZi-Yu Chen * Copyright (c) 2026 Nuvoton technology corporation. 4*80141041SZi-Yu Chen * 5*80141041SZi-Yu Chen * Author: Zi-Yu Chen <zychennvt@gmail.com> 6*80141041SZi-Yu Chen */ 7*80141041SZi-Yu Chen 8*80141041SZi-Yu Chen #include <linux/bitfield.h> 9*80141041SZi-Yu Chen #include <linux/bits.h> 10*80141041SZi-Yu Chen #include <linux/clk.h> 11*80141041SZi-Yu Chen #include <linux/err.h> 12*80141041SZi-Yu Chen #include <linux/init.h> 13*80141041SZi-Yu Chen #include <linux/interrupt.h> 14*80141041SZi-Yu Chen #include <linux/io.h> 15*80141041SZi-Yu Chen #include <linux/iopoll.h> 16*80141041SZi-Yu Chen #include <linux/kernel.h> 17*80141041SZi-Yu Chen #include <linux/module.h> 18*80141041SZi-Yu Chen #include <linux/moduleparam.h> 19*80141041SZi-Yu Chen #include <linux/of.h> 20*80141041SZi-Yu Chen #include <linux/platform_device.h> 21*80141041SZi-Yu Chen #include <linux/pm_wakeirq.h> 22*80141041SZi-Yu Chen #include <linux/property.h> 23*80141041SZi-Yu Chen #include <linux/types.h> 24*80141041SZi-Yu Chen #include <linux/watchdog.h> 25*80141041SZi-Yu Chen 26*80141041SZi-Yu Chen #define DRV_NAME "ma35d1-wdt" 27*80141041SZi-Yu Chen 28*80141041SZi-Yu Chen #define REG_WDT_CTL 0x00 29*80141041SZi-Yu Chen #define REG_WDT_RSTCNT 0x08 30*80141041SZi-Yu Chen 31*80141041SZi-Yu Chen #define TOUTSEL GENMASK(11, 8) 32*80141041SZi-Yu Chen #define WDTEN BIT(7) 33*80141041SZi-Yu Chen #define INTEN BIT(6) 34*80141041SZi-Yu Chen #define WKF BIT(5) 35*80141041SZi-Yu Chen #define WKEN BIT(4) 36*80141041SZi-Yu Chen #define IF BIT(3) 37*80141041SZi-Yu Chen #define RSTF BIT(2) 38*80141041SZi-Yu Chen #define RSTEN BIT(1) 39*80141041SZi-Yu Chen #define SYNC BIT(30) 40*80141041SZi-Yu Chen 41*80141041SZi-Yu Chen #define WDT_DEFAULT_TIMEOUT 32 42*80141041SZi-Yu Chen #define RESET_COUNTER 0x00005AA5 43*80141041SZi-Yu Chen 44*80141041SZi-Yu Chen static bool nowayout = WATCHDOG_NOWAYOUT; 45*80141041SZi-Yu Chen static unsigned int timeout; 46*80141041SZi-Yu Chen 47*80141041SZi-Yu Chen struct ma35d1_wdt_dev { 48*80141041SZi-Yu Chen struct watchdog_device wdt_dev; 49*80141041SZi-Yu Chen spinlock_t lock; 50*80141041SZi-Yu Chen void __iomem *wdt_base; 51*80141041SZi-Yu Chen struct clk *clk; 52*80141041SZi-Yu Chen unsigned long clk_rate; 53*80141041SZi-Yu Chen int irq; 54*80141041SZi-Yu Chen }; 55*80141041SZi-Yu Chen 56*80141041SZi-Yu Chen static int ma35d1_wdt_wait_sync(struct ma35d1_wdt_dev *ma35d1_wdt) 57*80141041SZi-Yu Chen { 58*80141041SZi-Yu Chen unsigned int val; 59*80141041SZi-Yu Chen 60*80141041SZi-Yu Chen return readl_relaxed_poll_timeout_atomic(ma35d1_wdt->wdt_base + 61*80141041SZi-Yu Chen REG_WDT_CTL, val, !(val & SYNC), 10, 125); 62*80141041SZi-Yu Chen } 63*80141041SZi-Yu Chen 64*80141041SZi-Yu Chen /** 65*80141041SZi-Yu Chen * ma35d1_wdt_stop - Stop the watchdog. 66*80141041SZi-Yu Chen * 67*80141041SZi-Yu Chen * @wdt_dev: watchdog device 68*80141041SZi-Yu Chen * 69*80141041SZi-Yu Chen * Read the contents of the CTL register, clear the WDTEN bit 70*80141041SZi-Yu Chen * in the register and set the access key for successful write. 71*80141041SZi-Yu Chen * 72*80141041SZi-Yu Chen * Return: 0 on success, negative error otherwise. 73*80141041SZi-Yu Chen */ 74*80141041SZi-Yu Chen static int ma35d1_wdt_stop(struct watchdog_device *wdt_dev) 75*80141041SZi-Yu Chen { 76*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = watchdog_get_drvdata(wdt_dev); 77*80141041SZi-Yu Chen unsigned int val; 78*80141041SZi-Yu Chen int ret; 79*80141041SZi-Yu Chen 80*80141041SZi-Yu Chen guard(spinlock_irqsave)(&ma35d1_wdt->lock); 81*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 82*80141041SZi-Yu Chen val &= ~WDTEN; 83*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 84*80141041SZi-Yu Chen ret = ma35d1_wdt_wait_sync(ma35d1_wdt); 85*80141041SZi-Yu Chen if (ret) { 86*80141041SZi-Yu Chen dev_err(wdt_dev->parent, "Wait for WDTEN SYNC timeout!\n"); 87*80141041SZi-Yu Chen return ret; 88*80141041SZi-Yu Chen } 89*80141041SZi-Yu Chen return 0; 90*80141041SZi-Yu Chen } 91*80141041SZi-Yu Chen 92*80141041SZi-Yu Chen static int ma35d1_wdt_ping(struct watchdog_device *wdt_dev) 93*80141041SZi-Yu Chen { 94*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = watchdog_get_drvdata(wdt_dev); 95*80141041SZi-Yu Chen 96*80141041SZi-Yu Chen writel_relaxed(RESET_COUNTER, ma35d1_wdt->wdt_base + REG_WDT_RSTCNT); 97*80141041SZi-Yu Chen 98*80141041SZi-Yu Chen return 0; 99*80141041SZi-Yu Chen } 100*80141041SZi-Yu Chen 101*80141041SZi-Yu Chen static int ma35d1_wdt_set_timeout(struct watchdog_device *wdt_dev, 102*80141041SZi-Yu Chen unsigned int timeout) 103*80141041SZi-Yu Chen { 104*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = watchdog_get_drvdata(wdt_dev); 105*80141041SZi-Yu Chen unsigned long target_ticks; 106*80141041SZi-Yu Chen unsigned int val, i; 107*80141041SZi-Yu Chen static const uint8_t toutsel_shifts[] = { 4, 6, 8, 10, 12, 108*80141041SZi-Yu Chen 14, 16, 18, 20 }; 109*80141041SZi-Yu Chen 110*80141041SZi-Yu Chen if (timeout < (ma35d1_wdt->wdt_dev.max_hw_heartbeat_ms / 1000)) { 111*80141041SZi-Yu Chen target_ticks = (unsigned long)timeout * ma35d1_wdt->clk_rate; 112*80141041SZi-Yu Chen 113*80141041SZi-Yu Chen for (i = 0; i < ARRAY_SIZE(toutsel_shifts); i++) { 114*80141041SZi-Yu Chen if ((1UL << toutsel_shifts[i]) >= target_ticks) 115*80141041SZi-Yu Chen break; 116*80141041SZi-Yu Chen } 117*80141041SZi-Yu Chen /* To avoid truncation errors (0 seconds) during division. */ 118*80141041SZi-Yu Chen wdt_dev->timeout = 119*80141041SZi-Yu Chen (1UL << toutsel_shifts[i]) / ma35d1_wdt->clk_rate; 120*80141041SZi-Yu Chen if (wdt_dev->timeout == 0) 121*80141041SZi-Yu Chen wdt_dev->timeout = 1; 122*80141041SZi-Yu Chen 123*80141041SZi-Yu Chen } else { 124*80141041SZi-Yu Chen i = ARRAY_SIZE(toutsel_shifts) - 1; 125*80141041SZi-Yu Chen wdt_dev->timeout = timeout; 126*80141041SZi-Yu Chen } 127*80141041SZi-Yu Chen 128*80141041SZi-Yu Chen guard(spinlock_irqsave)(&ma35d1_wdt->lock); 129*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 130*80141041SZi-Yu Chen val &= ~TOUTSEL; 131*80141041SZi-Yu Chen val |= FIELD_PREP(TOUTSEL, i); 132*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 133*80141041SZi-Yu Chen 134*80141041SZi-Yu Chen ma35d1_wdt_ping(wdt_dev); 135*80141041SZi-Yu Chen return 0; 136*80141041SZi-Yu Chen } 137*80141041SZi-Yu Chen 138*80141041SZi-Yu Chen static int ma35d1_wdt_start(struct watchdog_device *wdt_dev) 139*80141041SZi-Yu Chen { 140*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = watchdog_get_drvdata(wdt_dev); 141*80141041SZi-Yu Chen void __iomem *wdt_base = ma35d1_wdt->wdt_base; 142*80141041SZi-Yu Chen unsigned int val; 143*80141041SZi-Yu Chen int ret; 144*80141041SZi-Yu Chen 145*80141041SZi-Yu Chen ret = ma35d1_wdt_set_timeout(wdt_dev, wdt_dev->timeout); 146*80141041SZi-Yu Chen if (ret < 0) 147*80141041SZi-Yu Chen return ret; 148*80141041SZi-Yu Chen 149*80141041SZi-Yu Chen guard(spinlock_irqsave)(&ma35d1_wdt->lock); 150*80141041SZi-Yu Chen val = readl_relaxed(wdt_base + REG_WDT_CTL); 151*80141041SZi-Yu Chen val |= (WDTEN | RSTEN); 152*80141041SZi-Yu Chen 153*80141041SZi-Yu Chen writel_relaxed(val, wdt_base + REG_WDT_CTL); 154*80141041SZi-Yu Chen ret = ma35d1_wdt_wait_sync(ma35d1_wdt); 155*80141041SZi-Yu Chen if (ret) { 156*80141041SZi-Yu Chen dev_err(wdt_dev->parent, "Wait for WDTEN SYNC timeout!\n"); 157*80141041SZi-Yu Chen return ret; 158*80141041SZi-Yu Chen } 159*80141041SZi-Yu Chen 160*80141041SZi-Yu Chen writel_relaxed(RESET_COUNTER, wdt_base + REG_WDT_RSTCNT); 161*80141041SZi-Yu Chen 162*80141041SZi-Yu Chen return 0; 163*80141041SZi-Yu Chen } 164*80141041SZi-Yu Chen 165*80141041SZi-Yu Chen static const struct watchdog_info ma35d1_wdt_info = { 166*80141041SZi-Yu Chen .identity = DRV_NAME, 167*80141041SZi-Yu Chen .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | 168*80141041SZi-Yu Chen WDIOF_CARDRESET, 169*80141041SZi-Yu Chen }; 170*80141041SZi-Yu Chen 171*80141041SZi-Yu Chen static const struct watchdog_ops ma35d1_wdt_ops = { 172*80141041SZi-Yu Chen .owner = THIS_MODULE, 173*80141041SZi-Yu Chen .start = ma35d1_wdt_start, 174*80141041SZi-Yu Chen .stop = ma35d1_wdt_stop, 175*80141041SZi-Yu Chen .ping = ma35d1_wdt_ping, 176*80141041SZi-Yu Chen .set_timeout = ma35d1_wdt_set_timeout, 177*80141041SZi-Yu Chen }; 178*80141041SZi-Yu Chen 179*80141041SZi-Yu Chen static irqreturn_t ma35d1_wdt_isr(int irq, void *dev_id) 180*80141041SZi-Yu Chen { 181*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = dev_id; 182*80141041SZi-Yu Chen unsigned int val; 183*80141041SZi-Yu Chen 184*80141041SZi-Yu Chen /* Clear the flag if set */ 185*80141041SZi-Yu Chen guard(spinlock)(&ma35d1_wdt->lock); 186*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 187*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 188*80141041SZi-Yu Chen 189*80141041SZi-Yu Chen return IRQ_HANDLED; 190*80141041SZi-Yu Chen } 191*80141041SZi-Yu Chen 192*80141041SZi-Yu Chen static int ma35d1_wdt_probe(struct platform_device *pdev) 193*80141041SZi-Yu Chen { 194*80141041SZi-Yu Chen struct device *dev = &pdev->dev; 195*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt; 196*80141041SZi-Yu Chen unsigned long clk_rate, val; 197*80141041SZi-Yu Chen int ret; 198*80141041SZi-Yu Chen 199*80141041SZi-Yu Chen ma35d1_wdt = devm_kzalloc(dev, sizeof(*ma35d1_wdt), GFP_KERNEL); 200*80141041SZi-Yu Chen if (!ma35d1_wdt) 201*80141041SZi-Yu Chen return -ENOMEM; 202*80141041SZi-Yu Chen 203*80141041SZi-Yu Chen spin_lock_init(&ma35d1_wdt->lock); 204*80141041SZi-Yu Chen platform_set_drvdata(pdev, ma35d1_wdt); 205*80141041SZi-Yu Chen 206*80141041SZi-Yu Chen ma35d1_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0); 207*80141041SZi-Yu Chen if (IS_ERR(ma35d1_wdt->wdt_base)) 208*80141041SZi-Yu Chen return PTR_ERR(ma35d1_wdt->wdt_base); 209*80141041SZi-Yu Chen 210*80141041SZi-Yu Chen ma35d1_wdt->clk = devm_clk_get_enabled(dev, NULL); 211*80141041SZi-Yu Chen if (IS_ERR(ma35d1_wdt->clk)) 212*80141041SZi-Yu Chen return dev_err_probe(dev, PTR_ERR(ma35d1_wdt->clk), 213*80141041SZi-Yu Chen "Can't get Watchdog clock\n"); 214*80141041SZi-Yu Chen 215*80141041SZi-Yu Chen clk_rate = clk_get_rate(ma35d1_wdt->clk); 216*80141041SZi-Yu Chen if (!clk_rate) 217*80141041SZi-Yu Chen return -EINVAL; 218*80141041SZi-Yu Chen ma35d1_wdt->clk_rate = clk_rate; 219*80141041SZi-Yu Chen 220*80141041SZi-Yu Chen ma35d1_wdt->irq = platform_get_irq(pdev, 0); 221*80141041SZi-Yu Chen if (ma35d1_wdt->irq < 0) 222*80141041SZi-Yu Chen return dev_err_probe(dev, ma35d1_wdt->irq, 223*80141041SZi-Yu Chen "failed to get irq\n"); 224*80141041SZi-Yu Chen 225*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.info = &ma35d1_wdt_info; 226*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.ops = &ma35d1_wdt_ops; 227*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.timeout = WDT_DEFAULT_TIMEOUT; 228*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.min_timeout = 1; 229*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.max_hw_heartbeat_ms = (1U << 20) * 1000 / clk_rate; 230*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.parent = dev; 231*80141041SZi-Yu Chen 232*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 233*80141041SZi-Yu Chen if (val & RSTF) { 234*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.bootstatus = WDIOF_CARDRESET; 235*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 236*80141041SZi-Yu Chen } 237*80141041SZi-Yu Chen 238*80141041SZi-Yu Chen if (val & WDTEN) 239*80141041SZi-Yu Chen set_bit(WDOG_HW_RUNNING, &ma35d1_wdt->wdt_dev.status); 240*80141041SZi-Yu Chen 241*80141041SZi-Yu Chen watchdog_set_drvdata(&ma35d1_wdt->wdt_dev, ma35d1_wdt); 242*80141041SZi-Yu Chen watchdog_set_nowayout(&ma35d1_wdt->wdt_dev, nowayout); 243*80141041SZi-Yu Chen watchdog_init_timeout(&ma35d1_wdt->wdt_dev, timeout, &pdev->dev); 244*80141041SZi-Yu Chen 245*80141041SZi-Yu Chen ma35d1_wdt_set_timeout(&ma35d1_wdt->wdt_dev, 246*80141041SZi-Yu Chen ma35d1_wdt->wdt_dev.timeout); 247*80141041SZi-Yu Chen 248*80141041SZi-Yu Chen ret = devm_request_irq(dev, ma35d1_wdt->irq, ma35d1_wdt_isr, 0, 249*80141041SZi-Yu Chen dev_name(dev), ma35d1_wdt); 250*80141041SZi-Yu Chen if (ret) 251*80141041SZi-Yu Chen return dev_err_probe(dev, ret, "cannot claim IRQ %d\n", 252*80141041SZi-Yu Chen ma35d1_wdt->irq); 253*80141041SZi-Yu Chen 254*80141041SZi-Yu Chen if (device_property_read_bool(dev, "wakeup-source")) { 255*80141041SZi-Yu Chen ret = devm_device_init_wakeup(dev); 256*80141041SZi-Yu Chen if (ret) 257*80141041SZi-Yu Chen return ret; 258*80141041SZi-Yu Chen 259*80141041SZi-Yu Chen ret = devm_pm_set_wake_irq(dev, ma35d1_wdt->irq); 260*80141041SZi-Yu Chen if (ret) 261*80141041SZi-Yu Chen return ret; 262*80141041SZi-Yu Chen } 263*80141041SZi-Yu Chen 264*80141041SZi-Yu Chen watchdog_stop_on_reboot(&ma35d1_wdt->wdt_dev); 265*80141041SZi-Yu Chen watchdog_stop_on_unregister(&ma35d1_wdt->wdt_dev); 266*80141041SZi-Yu Chen ret = devm_watchdog_register_device(dev, &ma35d1_wdt->wdt_dev); 267*80141041SZi-Yu Chen if (ret) 268*80141041SZi-Yu Chen return ret; 269*80141041SZi-Yu Chen 270*80141041SZi-Yu Chen return 0; 271*80141041SZi-Yu Chen } 272*80141041SZi-Yu Chen 273*80141041SZi-Yu Chen static int ma35d1_wdt_suspend(struct device *dev) 274*80141041SZi-Yu Chen { 275*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = dev_get_drvdata(dev); 276*80141041SZi-Yu Chen 277*80141041SZi-Yu Chen if (watchdog_active(&ma35d1_wdt->wdt_dev) || 278*80141041SZi-Yu Chen watchdog_hw_running(&ma35d1_wdt->wdt_dev)) { 279*80141041SZi-Yu Chen u32 val; 280*80141041SZi-Yu Chen int ret; 281*80141041SZi-Yu Chen 282*80141041SZi-Yu Chen guard(spinlock_irqsave)(&ma35d1_wdt->lock); 283*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 284*80141041SZi-Yu Chen 285*80141041SZi-Yu Chen if (device_may_wakeup(dev)) { 286*80141041SZi-Yu Chen val &= ~RSTEN; 287*80141041SZi-Yu Chen val |= (INTEN | WKEN); 288*80141041SZi-Yu Chen } else { 289*80141041SZi-Yu Chen val &= ~(WDTEN | RSTEN); 290*80141041SZi-Yu Chen } 291*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 292*80141041SZi-Yu Chen ret = ma35d1_wdt_wait_sync(ma35d1_wdt); 293*80141041SZi-Yu Chen if (ret) { 294*80141041SZi-Yu Chen dev_err(dev, "Wait for WDTEN SYNC timeout!\n"); 295*80141041SZi-Yu Chen return ret; 296*80141041SZi-Yu Chen } 297*80141041SZi-Yu Chen } 298*80141041SZi-Yu Chen 299*80141041SZi-Yu Chen return 0; 300*80141041SZi-Yu Chen } 301*80141041SZi-Yu Chen 302*80141041SZi-Yu Chen static int ma35d1_wdt_resume(struct device *dev) 303*80141041SZi-Yu Chen { 304*80141041SZi-Yu Chen struct ma35d1_wdt_dev *ma35d1_wdt = dev_get_drvdata(dev); 305*80141041SZi-Yu Chen 306*80141041SZi-Yu Chen if (watchdog_active(&ma35d1_wdt->wdt_dev) || 307*80141041SZi-Yu Chen watchdog_hw_running(&ma35d1_wdt->wdt_dev)) { 308*80141041SZi-Yu Chen u32 val; 309*80141041SZi-Yu Chen int ret; 310*80141041SZi-Yu Chen 311*80141041SZi-Yu Chen guard(spinlock_irqsave)(&ma35d1_wdt->lock); 312*80141041SZi-Yu Chen val = readl_relaxed(ma35d1_wdt->wdt_base + REG_WDT_CTL); 313*80141041SZi-Yu Chen 314*80141041SZi-Yu Chen if (device_may_wakeup(dev)) { 315*80141041SZi-Yu Chen val |= RSTEN; 316*80141041SZi-Yu Chen val &= ~(INTEN | WKEN); 317*80141041SZi-Yu Chen } else { 318*80141041SZi-Yu Chen val |= (WDTEN | RSTEN); 319*80141041SZi-Yu Chen } 320*80141041SZi-Yu Chen writel_relaxed(val, ma35d1_wdt->wdt_base + REG_WDT_CTL); 321*80141041SZi-Yu Chen writel_relaxed(RESET_COUNTER, 322*80141041SZi-Yu Chen ma35d1_wdt->wdt_base + REG_WDT_RSTCNT); 323*80141041SZi-Yu Chen ret = ma35d1_wdt_wait_sync(ma35d1_wdt); 324*80141041SZi-Yu Chen if (ret) { 325*80141041SZi-Yu Chen dev_err(dev, "Wait for WDTEN SYNC timeout!\n"); 326*80141041SZi-Yu Chen return ret; 327*80141041SZi-Yu Chen } 328*80141041SZi-Yu Chen } 329*80141041SZi-Yu Chen return 0; 330*80141041SZi-Yu Chen } 331*80141041SZi-Yu Chen 332*80141041SZi-Yu Chen static DEFINE_SIMPLE_DEV_PM_OPS(ma35d1_wdt_pm_ops, ma35d1_wdt_suspend, 333*80141041SZi-Yu Chen ma35d1_wdt_resume); 334*80141041SZi-Yu Chen 335*80141041SZi-Yu Chen static const struct of_device_id ma35d1_wdt_dt_ids[] = { 336*80141041SZi-Yu Chen { .compatible = "nuvoton,ma35d1-wdt" }, 337*80141041SZi-Yu Chen { /* sentinel */ }, 338*80141041SZi-Yu Chen }; 339*80141041SZi-Yu Chen MODULE_DEVICE_TABLE(of, ma35d1_wdt_dt_ids); 340*80141041SZi-Yu Chen 341*80141041SZi-Yu Chen static struct platform_driver ma35d1_wdt_driver = { 342*80141041SZi-Yu Chen .probe = ma35d1_wdt_probe, 343*80141041SZi-Yu Chen .driver = { 344*80141041SZi-Yu Chen .name = DRV_NAME, 345*80141041SZi-Yu Chen .pm = pm_ptr(&ma35d1_wdt_pm_ops), 346*80141041SZi-Yu Chen .of_match_table = ma35d1_wdt_dt_ids, 347*80141041SZi-Yu Chen }, 348*80141041SZi-Yu Chen }; 349*80141041SZi-Yu Chen 350*80141041SZi-Yu Chen module_platform_driver(ma35d1_wdt_driver); 351*80141041SZi-Yu Chen 352*80141041SZi-Yu Chen module_param(timeout, uint, 0); 353*80141041SZi-Yu Chen MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds"); 354*80141041SZi-Yu Chen 355*80141041SZi-Yu Chen module_param(nowayout, bool, 0); 356*80141041SZi-Yu Chen MODULE_PARM_DESC( 357*80141041SZi-Yu Chen nowayout, 358*80141041SZi-Yu Chen "Watchdog cannot be stopped once started (default=" __MODULE_STRING( 359*80141041SZi-Yu Chen WATCHDOG_NOWAYOUT) ")"); 360*80141041SZi-Yu Chen 361*80141041SZi-Yu Chen MODULE_AUTHOR("Zi-Yu Chen <zychennvt@gmail.com>"); 362*80141041SZi-Yu Chen MODULE_DESCRIPTION("Nuvoton MA35D1 Watchdog Timer Driver"); 363*80141041SZi-Yu Chen MODULE_LICENSE("GPL"); 364