MLK-16891: watchdog: imx8_wdt: add pre_timeout notification
authorRobin Gong <yibin.gong@nxp.com>
Tue, 14 Nov 2017 09:03:02 +0000 (17:03 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:47:02 +0000 (15:47 -0500)
Add pre_timeout set and notification for i.mx8qm/qxp.

BuildInfo:
    - SCFW 36ff24f3, IMX-MKIMAGE 05d3d4a7, ATF 93dd1cc
    - U-Boot 2017.03-00684-g28c5243

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
drivers/soc/imx/sc/main/ipc.c
drivers/watchdog/imx8_wdt.c
include/soc/imx/fsl_sip.h

index 10f24d8..665b8e9 100644 (file)
@@ -367,6 +367,13 @@ int __init imx8_mu_init(void)
        if (sciErr)
                pr_info("Cannot request ON/OFF interrupt\n");
 
+       /* Request for the watchdog interrupt. */
+       sciErr = sc_irq_enable(mu_ipcHandle, SC_R_MU_0A, SC_IRQ_GROUP_WDOG,
+                              SC_IRQ_WDOG, true);
+
+       if (sciErr)
+               pr_info("Cannot request WDOG interrupt\n");
+
        pr_info("*****Initialized MU\n");
        return scu_mu_id;
 }
index 1083377..c78eb00 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/reboot.h>
 #include <linux/watchdog.h>
 #include <soc/imx/fsl_sip.h>
+#include <soc/imx8/sc/sci.h>
+#include <soc/imx8/sc/svc/irq/api.h>
 
 #define DEFAULT_TIMEOUT 10
 /*
 
 static struct watchdog_device imx8_wdd;
 
+static int imx8_wdt_notify(struct notifier_block *nb,
+                                     unsigned long event, void *group)
+{
+       /* ignore other irqs */
+       if (!(event & SC_IRQ_WDOG &&
+               (*(sc_irq_group_t *)group == SC_IRQ_GROUP_WDOG)))
+               return 0;
+
+       watchdog_notify_pretimeout(&imx8_wdd);
+
+       return 0;
+}
+
 static int imx8_wdt_ping(struct watchdog_device *wdog)
 {
        struct arm_smccc_res res;
@@ -73,18 +88,35 @@ static int imx8_wdt_set_timeout(struct watchdog_device *wdog,
        return res.a0;
 }
 
+static int imx8_wdt_set_pretimeout(struct watchdog_device *wdog,
+                                  unsigned int new_pretimeout)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(FSL_SIP_SRTC, FSL_SIP_SRTC_SET_PRETIME_WDOG,
+                       new_pretimeout * 1000, 0, 0, 0, 0, 0,
+                       &res);
+
+       return res.a0;
+}
+
 static const struct watchdog_ops imx8_wdt_ops = {
        .owner = THIS_MODULE,
        .start = imx8_wdt_start,
        .stop  = imx8_wdt_stop,
        .ping  = imx8_wdt_ping,
        .set_timeout = imx8_wdt_set_timeout,
+       .set_pretimeout = imx8_wdt_set_pretimeout,
 };
 
 static const struct watchdog_info imx8_wdt_info = {
        .identity       = "i.MX8 watchdog timer",
        .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-                         WDIOF_MAGICCLOSE,
+                         WDIOF_MAGICCLOSE | WDIOF_PRETIMEOUT,
+};
+
+static struct notifier_block imx8_wdt_notifier = {
+       .notifier_call = imx8_wdt_notify,
 };
 
 static int imx8_wdt_probe(struct platform_device *pdev)
@@ -114,7 +146,7 @@ static int imx8_wdt_probe(struct platform_device *pdev)
                return err;
        }
 
-       return 0;
+       return register_scu_notifier(&imx8_wdt_notifier);
 }
 
 static int imx8_wdt_remove(struct platform_device *pdev)
index 51d3462..11679d2 100644 (file)
@@ -27,6 +27,8 @@
 #define FSL_SIP_SRTC_SET_WDOG_ACT      0x03
 #define FSL_SIP_SRTC_PING_WDOG         0x04
 #define FSL_SIP_SRTC_SET_TIMEOUT_WDOG  0x05
+#define FSL_SIP_SRTC_GET_WDOG_STAT     0x06
+#define FSL_SIP_SRTC_SET_PRETIME_WDOG  0x07
 
 #define FSL_SIP_DDR_DVFS               0xc2000004