Merge tag 'linux-watchdog-5.20-rc1' of git://www.linux-watchdog.org/linux-watchdog
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Aug 2022 22:04:04 +0000 (15:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Aug 2022 22:04:04 +0000 (15:04 -0700)
Pull watchdog updates from Wim Van Sebroeck:

 - add RTL9310 support

 - sp805_wdt: add arm cmsdk apb wdt support

 - Remove #ifdef guards for PM related functions for several watchdog
   device drivers

 - pm8916_wdt reboot improvements

 - Several other fixes and improvements

* tag 'linux-watchdog-5.20-rc1' of git://www.linux-watchdog.org/linux-watchdog: (24 commits)
  watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in armada_37xx_wdt_probe()
  watchdog: dw_wdt: Fix comment typo
  watchdog: Fix comment typo
  dt-bindings: watchdog: Add fsl,scu-wdt yaml file
  watchdog:Fix typo in comment
  watchdog: pm8916_wdt: Handle watchdog enabled by bootloader
  watchdog: pm8916_wdt: Report reboot reason
  watchdog: pm8916_wdt: Avoid read of write-only PET register
  watchdog: wdat_wdt: Remove #ifdef guards for PM related functions
  watchdog: tegra_wdt: Remove #ifdef guards for PM related functions
  watchdog: st_lpc_wdt: Remove #ifdef guards for PM related functions
  watchdog: sama5d4_wdt: Remove #ifdef guards for PM related functions
  watchdog: s3c2410_wdt: Remove #ifdef guards for PM related functions
  watchdog: mtk_wdt: Remove #ifdef guards for PM related functions
  watchdog: dw_wdt: Remove #ifdef guards for PM related functions
  watchdog: bcm7038_wdt: Remove #ifdef guards for PM related functions
  watchdog: realtek-otto: add RTL9310 support
  dt-bindings: watchdog: realtek,otto-wdt: add RTL9310
  watchdog: sp805_wdt: add arm cmsdk apb wdt support
  watchdog: sp5100_tco: Fix a memory leak of EFCH MMIO resource
  ...

19 files changed:
Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml
drivers/watchdog/armada_37xx_wdt.c
drivers/watchdog/bcm7038_wdt.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/dw_wdt.c
drivers/watchdog/f71808e_wdt.c
drivers/watchdog/max77620_wdt.c
drivers/watchdog/mtk_wdt.c
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/pm8916_wdt.c
drivers/watchdog/realtek_otto_wdt.c
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/sama5d4_wdt.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/sp805_wdt.c
drivers/watchdog/st_lpc_wdt.c
drivers/watchdog/tegra_wdt.c
drivers/watchdog/wdat_wdt.c

index 2bd6b4a..d8ac0be 100644 (file)
@@ -24,6 +24,7 @@ properties:
               - qcom,apss-wdt-sc8280xp
               - qcom,apss-wdt-sdm845
               - qcom,apss-wdt-sdx55
+              - qcom,apss-wdt-sdx65
               - qcom,apss-wdt-sm6350
               - qcom,apss-wdt-sm8150
               - qcom,apss-wdt-sm8250
index 11b220a..099245f 100644 (file)
@@ -29,6 +29,7 @@ properties:
       - realtek,rtl8380-wdt
       - realtek,rtl8390-wdt
       - realtek,rtl9300-wdt
+      - realtek,rtl9310-wdt
 
   reg:
     maxItems: 1
index 1635f42..854b1cc 100644 (file)
@@ -274,6 +274,8 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
        dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+       if (!dev->reg)
+               return -ENOMEM;
 
        /* init clock */
        dev->clk = devm_clk_get(&pdev->dev, NULL);
index 1ffcf6a..9388838 100644 (file)
@@ -192,7 +192,6 @@ static int bcm7038_wdt_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int bcm7038_wdt_suspend(struct device *dev)
 {
        struct bcm7038_watchdog *wdt = dev_get_drvdata(dev);
@@ -212,10 +211,9 @@ static int bcm7038_wdt_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend,
-                        bcm7038_wdt_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops,
+                               bcm7038_wdt_suspend, bcm7038_wdt_resume);
 
 static const struct of_device_id bcm7038_wdt_match[] = {
        { .compatible = "brcm,bcm6345-wdt" },
@@ -236,7 +234,7 @@ static struct platform_driver bcm7038_wdt_driver = {
        .driver         = {
                .name           = "bcm7038-wdt",
                .of_match_table = bcm7038_wdt_match,
-               .pm             = &bcm7038_wdt_pm_ops,
+               .pm             = pm_sleep_ptr(&bcm7038_wdt_pm_ops),
        }
 };
 module_platform_driver(bcm7038_wdt_driver);
index 5e4dc1a..75da5cd 100644 (file)
@@ -74,7 +74,7 @@ static unsigned long long period_to_sec(unsigned int period)
 /*
  * This procedure will find the highest period which will give a timeout
  * greater than the one required. e.g. for a bus speed of 66666666 and
- * and a parameter of 2 secs, then this procedure will return a value of 38.
+ * a parameter of 2 secs, then this procedure will return a value of 38.
  */
 static unsigned int sec_to_period(unsigned int secs)
 {
index cd57884..52962e8 100644 (file)
@@ -218,7 +218,7 @@ static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s)
 
        /*
         * Set the new value in the watchdog.  Some versions of dw_wdt
-        * have have TOPINIT in the TIMEOUT_RANGE register (as per
+        * have TOPINIT in the TIMEOUT_RANGE register (as per
         * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1).  On those we
         * effectively get a pat of the watchdog right here.
         */
@@ -375,7 +375,6 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int dw_wdt_suspend(struct device *dev)
 {
        struct dw_wdt *dw_wdt = dev_get_drvdata(dev);
@@ -410,9 +409,8 @@ static int dw_wdt_resume(struct device *dev)
 
        return 0;
 }
-#endif /* CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume);
 
 /*
  * In case if DW WDT IP core is synthesized with fixed TOP feature disabled the
@@ -710,7 +708,7 @@ static struct platform_driver dw_wdt_driver = {
        .driver         = {
                .name   = "dw_wdt",
                .of_match_table = of_match_ptr(dw_wdt_of_match),
-               .pm     = &dw_wdt_pm_ops,
+               .pm     = pm_sleep_ptr(&dw_wdt_pm_ops),
        },
 };
 
index 7f59c68..6a16d3d 100644 (file)
@@ -634,7 +634,9 @@ static int __init fintek_wdt_init(void)
 
        pdata.type = ret;
 
-       platform_driver_register(&fintek_wdt_driver);
+       ret = platform_driver_register(&fintek_wdt_driver);
+       if (ret)
+               return ret;
 
        wdt_res.name = "superio port";
        wdt_res.flags = IORESOURCE_IO;
index b76ad6b..33835c0 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 2022 Luca Ceresoli
  *
  * Author: Laxman Dewangan <ldewangan@nvidia.com>
- * Author: Luca Ceresoli <luca@lucaceresoli.net>
+ * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
  */
 
 #include <linux/err.h>
@@ -260,5 +260,5 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
        "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
+MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
 MODULE_LICENSE("GPL v2");
index f0d4e3c..e977875 100644 (file)
@@ -401,7 +401,6 @@ static int mtk_wdt_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int mtk_wdt_suspend(struct device *dev)
 {
        struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
@@ -423,7 +422,6 @@ static int mtk_wdt_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static const struct of_device_id mtk_wdt_dt_ids[] = {
        { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
@@ -437,16 +435,14 @@ static const struct of_device_id mtk_wdt_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
 
-static const struct dev_pm_ops mtk_wdt_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(mtk_wdt_suspend,
-                               mtk_wdt_resume)
-};
+static DEFINE_SIMPLE_DEV_PM_OPS(mtk_wdt_pm_ops,
+                               mtk_wdt_suspend, mtk_wdt_resume);
 
 static struct platform_driver mtk_wdt_driver = {
        .probe          = mtk_wdt_probe,
        .driver         = {
                .name           = DRV_NAME,
-               .pm             = &mtk_wdt_pm_ops,
+               .pm             = pm_sleep_ptr(&mtk_wdt_pm_ops),
                .of_match_table = mtk_wdt_dt_ids,
        },
 };
index 9f9a340..c7f745c 100644 (file)
@@ -442,7 +442,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
        }
 }
 
-/* -- Notifier funtions -----------------------------------------*/
+/* -- Notifier functions -----------------------------------------*/
 
 /**
  *     pc87413_notify_sys:
index 0937b8d..f4bfbff 100644 (file)
@@ -9,6 +9,12 @@
 #include <linux/regmap.h>
 #include <linux/watchdog.h>
 
+#define PON_POFF_REASON1               0x0c
+#define PON_POFF_REASON1_PMIC_WD       BIT(2)
+#define PON_POFF_REASON2               0x0d
+#define PON_POFF_REASON2_UVLO          BIT(5)
+#define PON_POFF_REASON2_OTST3         BIT(6)
+
 #define PON_INT_RT_STS                 0x10
 #define PMIC_WD_BARK_STS_BIT           BIT(6)
 
@@ -58,9 +64,8 @@ static int pm8916_wdt_ping(struct watchdog_device *wdev)
 {
        struct pm8916_wdt *wdt = watchdog_get_drvdata(wdev);
 
-       return regmap_update_bits(wdt->regmap,
-                                 wdt->baseaddr + PON_PMIC_WD_RESET_PET,
-                                 WATCHDOG_PET_BIT, WATCHDOG_PET_BIT);
+       return regmap_write(wdt->regmap, wdt->baseaddr + PON_PMIC_WD_RESET_PET,
+                           WATCHDOG_PET_BIT);
 }
 
 static int pm8916_wdt_configure_timers(struct watchdog_device *wdev)
@@ -111,12 +116,14 @@ static irqreturn_t pm8916_wdt_isr(int irq, void *arg)
 }
 
 static const struct watchdog_info pm8916_wdt_ident = {
-       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
+                  WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER,
        .identity = "QCOM PM8916 PON WDT",
 };
 
 static const struct watchdog_info pm8916_wdt_pt_ident = {
        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
+                  WDIOF_OVERHEAT | WDIOF_CARDRESET | WDIOF_POWERUNDER |
                   WDIOF_PRETIMEOUT,
        .identity = "QCOM PM8916 PON WDT",
 };
@@ -135,7 +142,9 @@ static int pm8916_wdt_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct pm8916_wdt *wdt;
        struct device *parent;
+       unsigned int val;
        int err, irq;
+       u8 poff[2];
 
        wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
        if (!wdt)
@@ -176,6 +185,30 @@ static int pm8916_wdt_probe(struct platform_device *pdev)
                wdt->wdev.info = &pm8916_wdt_ident;
        }
 
+       err = regmap_bulk_read(wdt->regmap, wdt->baseaddr + PON_POFF_REASON1,
+                              &poff, ARRAY_SIZE(poff));
+       if (err) {
+               dev_err(dev, "failed to read POFF reason: %d\n", err);
+               return err;
+       }
+
+       dev_dbg(dev, "POFF reason: %#x %#x\n", poff[0], poff[1]);
+       if (poff[0] & PON_POFF_REASON1_PMIC_WD)
+               wdt->wdev.bootstatus |= WDIOF_CARDRESET;
+       if (poff[1] & PON_POFF_REASON2_UVLO)
+               wdt->wdev.bootstatus |= WDIOF_POWERUNDER;
+       if (poff[1] & PON_POFF_REASON2_OTST3)
+               wdt->wdev.bootstatus |= WDIOF_OVERHEAT;
+
+       err = regmap_read(wdt->regmap, wdt->baseaddr + PON_PMIC_WD_RESET_S2_CTL2,
+                         &val);
+       if (err)  {
+               dev_err(dev, "failed to check if watchdog is active: %d\n", err);
+               return err;
+       }
+       if (val & S2_RESET_EN_BIT)
+               set_bit(WDOG_HW_RUNNING, &wdt->wdev.status);
+
        /* Configure watchdog to hard-reset mode */
        err = regmap_write(wdt->regmap,
                           wdt->baseaddr + PON_PMIC_WD_RESET_S2_CTL,
index 60058a0..2a5298c 100644 (file)
@@ -366,6 +366,7 @@ static const struct of_device_id otto_wdt_ids[] = {
        { .compatible = "realtek,rtl8380-wdt" },
        { .compatible = "realtek,rtl8390-wdt" },
        { .compatible = "realtek,rtl9300-wdt" },
+       { .compatible = "realtek,rtl9310-wdt" },
        { }
 };
 MODULE_DEVICE_TABLE(of, otto_wdt_ids);
index 6db22f2..9591939 100644 (file)
@@ -845,8 +845,6 @@ static void s3c2410wdt_shutdown(struct platform_device *dev)
        s3c2410wdt_stop(&wdt->wdt_device);
 }
 
-#ifdef CONFIG_PM_SLEEP
-
 static int s3c2410wdt_suspend(struct device *dev)
 {
        int ret;
@@ -885,10 +883,9 @@ static int s3c2410wdt_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops, s3c2410wdt_suspend,
-                       s3c2410wdt_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops,
+                               s3c2410wdt_suspend, s3c2410wdt_resume);
 
 static struct platform_driver s3c2410wdt_driver = {
        .probe          = s3c2410wdt_probe,
@@ -897,7 +894,7 @@ static struct platform_driver s3c2410wdt_driver = {
        .id_table       = s3c2410_wdt_ids,
        .driver         = {
                .name   = "s3c2410-wdt",
-               .pm     = &s3c2410wdt_pm_ops,
+               .pm     = pm_sleep_ptr(&s3c2410wdt_pm_ops),
                .of_match_table = of_match_ptr(s3c2410_wdt_match),
        },
 };
index ec20ad4..aeee934 100644 (file)
@@ -339,7 +339,6 @@ static const struct of_device_id sama5d4_wdt_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match);
 
-#ifdef CONFIG_PM_SLEEP
 static int sama5d4_wdt_suspend_late(struct device *dev)
 {
        struct sama5d4_wdt *wdt = dev_get_drvdata(dev);
@@ -366,18 +365,17 @@ static int sama5d4_wdt_resume_early(struct device *dev)
 
        return 0;
 }
-#endif
 
 static const struct dev_pm_ops sama5d4_wdt_pm_ops = {
-       SET_LATE_SYSTEM_SLEEP_PM_OPS(sama5d4_wdt_suspend_late,
-                       sama5d4_wdt_resume_early)
+       LATE_SYSTEM_SLEEP_PM_OPS(sama5d4_wdt_suspend_late,
+                                sama5d4_wdt_resume_early)
 };
 
 static struct platform_driver sama5d4_wdt_driver = {
        .probe          = sama5d4_wdt_probe,
        .driver         = {
                .name   = "sama5d4_wdt",
-               .pm     = &sama5d4_wdt_pm_ops,
+               .pm     = pm_sleep_ptr(&sama5d4_wdt_pm_ops),
                .of_match_table = sama5d4_wdt_of_match,
        }
 };
index 86ffb58..ae54dd3 100644 (file)
@@ -402,6 +402,7 @@ out:
                iounmap(addr);
 
        release_resource(res);
+       kfree(res);
 
        return ret;
 }
index f9479a3..78ba366 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * drivers/char/watchdog/sp805-wdt.c
  *
@@ -341,6 +342,10 @@ static const struct amba_id sp805_wdt_ids[] = {
                .id     = 0x00141805,
                .mask   = 0x00ffffff,
        },
+       {
+               .id     = 0x001bb824,
+               .mask   = 0x00ffffff,
+       },
        { 0, 0 },
 };
 
index 14ab655..39abecd 100644 (file)
@@ -248,7 +248,6 @@ static int st_wdog_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int st_wdog_suspend(struct device *dev)
 {
        struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
@@ -285,16 +284,14 @@ static int st_wdog_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(st_wdog_pm_ops,
-                        st_wdog_suspend,
-                        st_wdog_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(st_wdog_pm_ops,
+                               st_wdog_suspend, st_wdog_resume);
 
 static struct platform_driver st_wdog_driver = {
        .driver = {
                .name = "st-lpc-wdt",
-               .pm = &st_wdog_pm_ops,
+               .pm = pm_sleep_ptr(&st_wdog_pm_ops),
                .of_match_table = st_wdog_match,
        },
        .probe = st_wdog_probe,
index dfe06e5..d5de6c0 100644 (file)
@@ -230,8 +230,7 @@ static int tegra_wdt_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tegra_wdt_runtime_suspend(struct device *dev)
+static int tegra_wdt_suspend(struct device *dev)
 {
        struct tegra_wdt *wdt = dev_get_drvdata(dev);
 
@@ -241,7 +240,7 @@ static int tegra_wdt_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int tegra_wdt_runtime_resume(struct device *dev)
+static int tegra_wdt_resume(struct device *dev)
 {
        struct tegra_wdt *wdt = dev_get_drvdata(dev);
 
@@ -250,7 +249,6 @@ static int tegra_wdt_runtime_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static const struct of_device_id tegra_wdt_of_match[] = {
        { .compatible = "nvidia,tegra30-timer", },
@@ -258,16 +256,14 @@ static const struct of_device_id tegra_wdt_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_wdt_of_match);
 
-static const struct dev_pm_ops tegra_wdt_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(tegra_wdt_runtime_suspend,
-                               tegra_wdt_runtime_resume)
-};
+static DEFINE_SIMPLE_DEV_PM_OPS(tegra_wdt_pm_ops,
+                               tegra_wdt_suspend, tegra_wdt_resume);
 
 static struct platform_driver tegra_wdt_driver = {
        .probe          = tegra_wdt_probe,
        .driver         = {
                .name   = "tegra-wdt",
-               .pm     = &tegra_wdt_pm_ops,
+               .pm     = pm_sleep_ptr(&tegra_wdt_pm_ops),
                .of_match_table = tegra_wdt_of_match,
        },
 };
index e6f95e9..aeadaa0 100644 (file)
@@ -467,7 +467,6 @@ static int wdat_wdt_probe(struct platform_device *pdev)
        return devm_watchdog_register_device(dev, &wdat->wdd);
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int wdat_wdt_suspend_noirq(struct device *dev)
 {
        struct wdat_wdt *wdat = dev_get_drvdata(dev);
@@ -528,18 +527,16 @@ static int wdat_wdt_resume_noirq(struct device *dev)
 
        return wdat_wdt_start(&wdat->wdd);
 }
-#endif
 
 static const struct dev_pm_ops wdat_wdt_pm_ops = {
-       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(wdat_wdt_suspend_noirq,
-                                     wdat_wdt_resume_noirq)
+       NOIRQ_SYSTEM_SLEEP_PM_OPS(wdat_wdt_suspend_noirq, wdat_wdt_resume_noirq)
 };
 
 static struct platform_driver wdat_wdt_driver = {
        .probe = wdat_wdt_probe,
        .driver = {
                .name = "wdat_wdt",
-               .pm = &wdat_wdt_pm_ops,
+               .pm = pm_sleep_ptr(&wdat_wdt_pm_ops),
        },
 };