On Thu 05 Sep 09:21 PDT 2019, Jorge Ramirez-Ortiz wrote: > Use the bark interrupt to notify the bark event. Since the bark and bite > timeouts are identical, increase the bite timeout by one second so > that the bark event can be logged to the console. > Afaict you should tie the bark to the "pretimeout" in the watchdog framework , which would allow the user to specify a pretimeout and configure what should happen at the bark (just a pr_alert() or panic()). Regards, Bjorn > Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@xxxxxxxxxx> > --- > drivers/watchdog/qcom-wdt.c | 42 ++++++++++++++++++++++++++++++++++--- > 1 file changed, 39 insertions(+), 3 deletions(-) > > diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c > index 7be7f87be28f..5eaf92084b93 100644 > --- a/drivers/watchdog/qcom-wdt.c > +++ b/drivers/watchdog/qcom-wdt.c > @@ -10,6 +10,7 @@ > #include <linux/platform_device.h> > #include <linux/watchdog.h> > #include <linux/of_device.h> > +#include <linux/interrupt.h> > > enum wdt_reg { > WDT_RST, > @@ -41,6 +42,8 @@ struct qcom_wdt { > unsigned long rate; > void __iomem *base; > const u32 *layout; > + unsigned int irq; > + const struct device *dev; > }; > > static void __iomem *wdt_addr(struct qcom_wdt *wdt, enum wdt_reg reg) > @@ -54,15 +57,37 @@ struct qcom_wdt *to_qcom_wdt(struct watchdog_device *wdd) > return container_of(wdd, struct qcom_wdt, wdd); > } > > +static inline int qcom_wdt_enable(struct qcom_wdt *wdt) > +{ > + if (wdt->irq < 0) > + return 1; > + > + /* enable timeout with interrupt */ > + return 3; > +} > + > +static irqreturn_t qcom_wdt_irq(int irq, void *cookie) > +{ > + struct qcom_wdt *wdt = (struct qcom_wdt *) cookie; > + > + dev_warn(wdt->dev, "barking, one second countdown to reset\n"); > + > + return IRQ_HANDLED; > +} > + > static int qcom_wdt_start(struct watchdog_device *wdd) > { > struct qcom_wdt *wdt = to_qcom_wdt(wdd); > + unsigned int bark, bite; > + > + bark = wdd->timeout; > + bite = wdt->irq < 0 ? bark : bark + 1; > > writel(0, wdt_addr(wdt, WDT_EN)); > writel(1, wdt_addr(wdt, WDT_RST)); > - writel(wdd->timeout * wdt->rate, wdt_addr(wdt, WDT_BARK_TIME)); > - writel(wdd->timeout * wdt->rate, wdt_addr(wdt, WDT_BITE_TIME)); > - writel(1, wdt_addr(wdt, WDT_EN)); > + writel(bark * wdt->rate, wdt_addr(wdt, WDT_BARK_TIME)); > + writel(bite * wdt->rate, wdt_addr(wdt, WDT_BITE_TIME)); > + writel(qcom_wdt_enable(wdt), wdt_addr(wdt, WDT_EN)); > return 0; > } > > @@ -210,10 +235,21 @@ static int qcom_wdt_probe(struct platform_device *pdev) > wdt->wdd.max_timeout = 0x10000000U / wdt->rate; > wdt->wdd.parent = dev; > wdt->layout = regs; > + wdt->dev = &pdev->dev; > > if (readl(wdt_addr(wdt, WDT_STS)) & 1) > wdt->wdd.bootstatus = WDIOF_CARDRESET; > > + wdt->irq = platform_get_irq(pdev, 0); > + if (wdt->irq >= 0) { > + ret = devm_request_irq(&pdev->dev, wdt->irq, qcom_wdt_irq, > + IRQF_TRIGGER_RISING, "wdog_bark", wdt); > + if (ret) { > + dev_err(&pdev->dev, "failed to request irq\n"); > + return ret; > + } > + } > + > /* > * If 'timeout-sec' unspecified in devicetree, assume a 30 second > * default, unless the max timeout is less than 30 seconds, then use > -- > 2.23.0 >