| From 000de5417107623925a4cf0310579f744ff43c28 Mon Sep 17 00:00:00 2001 |
| From: Ansuel Smith <ansuelsmth@gmail.com> |
| Date: Tue, 4 Feb 2020 20:56:48 +0100 |
| Subject: watchdog: qcom-wdt: disable pretimeout on timer platform |
| |
| Some platform like ipq806x doesn't support pretimeout and define |
| some interrupts used by qcom,msm-timer. Change the driver to check |
| and use pretimeout only on qcom,kpss-wdt as it's the only platform |
| that actually supports it. |
| |
| Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com> |
| Reviewed-by: Guenter Roeck <linux@roeck-us.net> |
| Link: https://lore.kernel.org/r/20200204195648.23350-1-ansuelsmth@gmail.com |
| [groeck: Conflict resolution] |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org> |
| --- |
| drivers/watchdog/qcom-wdt.c | 31 +++++++++++++++++++++++-------- |
| 1 file changed, 23 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/watchdog/qcom-wdt.c |
| +++ b/drivers/watchdog/qcom-wdt.c |
| @@ -39,6 +39,11 @@ static const u32 reg_offset_data_kpss[] |
| [WDT_BITE_TIME] = 0x14, |
| }; |
| |
| +struct qcom_wdt_match_data { |
| + const u32 *offset; |
| + bool pretimeout; |
| +}; |
| + |
| struct qcom_wdt { |
| struct watchdog_device wdd; |
| unsigned long rate; |
| @@ -168,19 +173,29 @@ static void qcom_clk_disable_unprepare(v |
| clk_disable_unprepare(data); |
| } |
| |
| +static const struct qcom_wdt_match_data match_data_apcs_tmr = { |
| + .offset = reg_offset_data_apcs_tmr, |
| + .pretimeout = false, |
| +}; |
| + |
| +static const struct qcom_wdt_match_data match_data_kpss = { |
| + .offset = reg_offset_data_kpss, |
| + .pretimeout = true, |
| +}; |
| + |
| static int qcom_wdt_probe(struct platform_device *pdev) |
| { |
| struct device *dev = &pdev->dev; |
| struct qcom_wdt *wdt; |
| struct resource *res; |
| struct device_node *np = dev->of_node; |
| - const u32 *regs; |
| + const struct qcom_wdt_match_data *data; |
| u32 percpu_offset; |
| int irq, ret; |
| struct clk *clk; |
| |
| - regs = of_device_get_match_data(dev); |
| - if (!regs) { |
| + data = of_device_get_match_data(dev); |
| + if (!data) { |
| dev_err(dev, "Unsupported QCOM WDT module\n"); |
| return -ENODEV; |
| } |
| @@ -236,7 +251,7 @@ static int qcom_wdt_probe(struct platfor |
| |
| /* check if there is pretimeout support */ |
| irq = platform_get_irq_optional(pdev, 0); |
| - if (irq > 0) { |
| + if (data->pretimeout && irq > 0) { |
| ret = devm_request_irq(dev, irq, qcom_wdt_isr, |
| IRQF_TRIGGER_RISING, |
| "wdt_bark", &wdt->wdd); |
| @@ -256,7 +271,7 @@ static int qcom_wdt_probe(struct platfor |
| wdt->wdd.min_timeout = 1; |
| wdt->wdd.max_timeout = 0x10000000U / wdt->rate; |
| wdt->wdd.parent = dev; |
| - wdt->layout = regs; |
| + wdt->layout = data->offset; |
| |
| if (readl(wdt_addr(wdt, WDT_STS)) & 1) |
| wdt->wdd.bootstatus = WDIOF_CARDRESET; |
| @@ -300,9 +315,9 @@ static int __maybe_unused qcom_wdt_resum |
| static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume); |
| |
| static const struct of_device_id qcom_wdt_of_table[] = { |
| - { .compatible = "qcom,kpss-timer", .data = reg_offset_data_apcs_tmr }, |
| - { .compatible = "qcom,scss-timer", .data = reg_offset_data_apcs_tmr }, |
| - { .compatible = "qcom,kpss-wdt", .data = reg_offset_data_kpss }, |
| + { .compatible = "qcom,kpss-timer", .data = &match_data_apcs_tmr }, |
| + { .compatible = "qcom,scss-timer", .data = &match_data_apcs_tmr }, |
| + { .compatible = "qcom,kpss-wdt", .data = &match_data_kpss }, |
| { }, |
| }; |
| MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); |