1bd44fd5a0b2517c380eb7d4871fcb4a78808114
[openwrt/openwrt.git] /
1 From 000de5417107623925a4cf0310579f744ff43c28 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Tue, 4 Feb 2020 20:56:48 +0100
4 Subject: watchdog: qcom-wdt: disable pretimeout on timer platform
5
6 Some platform like ipq806x doesn't support pretimeout and define
7 some interrupts used by qcom,msm-timer. Change the driver to check
8 and use pretimeout only on qcom,kpss-wdt as it's the only platform
9 that actually supports it.
10
11 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
12 Reviewed-by: Guenter Roeck <linux@roeck-us.net>
13 Link: https://lore.kernel.org/r/20200204195648.23350-1-ansuelsmth@gmail.com
14 [groeck: Conflict resolution]
15 Signed-off-by: Guenter Roeck <linux@roeck-us.net>
16 Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
17 ---
18 drivers/watchdog/qcom-wdt.c | 31 +++++++++++++++++++++++--------
19 1 file changed, 23 insertions(+), 8 deletions(-)
20
21 --- a/drivers/watchdog/qcom-wdt.c
22 +++ b/drivers/watchdog/qcom-wdt.c
23 @@ -39,6 +39,11 @@ static const u32 reg_offset_data_kpss[]
24 [WDT_BITE_TIME] = 0x14,
25 };
26
27 +struct qcom_wdt_match_data {
28 + const u32 *offset;
29 + bool pretimeout;
30 +};
31 +
32 struct qcom_wdt {
33 struct watchdog_device wdd;
34 unsigned long rate;
35 @@ -168,19 +173,29 @@ static void qcom_clk_disable_unprepare(v
36 clk_disable_unprepare(data);
37 }
38
39 +static const struct qcom_wdt_match_data match_data_apcs_tmr = {
40 + .offset = reg_offset_data_apcs_tmr,
41 + .pretimeout = false,
42 +};
43 +
44 +static const struct qcom_wdt_match_data match_data_kpss = {
45 + .offset = reg_offset_data_kpss,
46 + .pretimeout = true,
47 +};
48 +
49 static int qcom_wdt_probe(struct platform_device *pdev)
50 {
51 struct device *dev = &pdev->dev;
52 struct qcom_wdt *wdt;
53 struct resource *res;
54 struct device_node *np = dev->of_node;
55 - const u32 *regs;
56 + const struct qcom_wdt_match_data *data;
57 u32 percpu_offset;
58 int irq, ret;
59 struct clk *clk;
60
61 - regs = of_device_get_match_data(dev);
62 - if (!regs) {
63 + data = of_device_get_match_data(dev);
64 + if (!data) {
65 dev_err(dev, "Unsupported QCOM WDT module\n");
66 return -ENODEV;
67 }
68 @@ -236,7 +251,7 @@ static int qcom_wdt_probe(struct platfor
69
70 /* check if there is pretimeout support */
71 irq = platform_get_irq_optional(pdev, 0);
72 - if (irq > 0) {
73 + if (data->pretimeout && irq > 0) {
74 ret = devm_request_irq(dev, irq, qcom_wdt_isr,
75 IRQF_TRIGGER_RISING,
76 "wdt_bark", &wdt->wdd);
77 @@ -256,7 +271,7 @@ static int qcom_wdt_probe(struct platfor
78 wdt->wdd.min_timeout = 1;
79 wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
80 wdt->wdd.parent = dev;
81 - wdt->layout = regs;
82 + wdt->layout = data->offset;
83
84 if (readl(wdt_addr(wdt, WDT_STS)) & 1)
85 wdt->wdd.bootstatus = WDIOF_CARDRESET;
86 @@ -300,9 +315,9 @@ static int __maybe_unused qcom_wdt_resum
87 static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume);
88
89 static const struct of_device_id qcom_wdt_of_table[] = {
90 - { .compatible = "qcom,kpss-timer", .data = reg_offset_data_apcs_tmr },
91 - { .compatible = "qcom,scss-timer", .data = reg_offset_data_apcs_tmr },
92 - { .compatible = "qcom,kpss-wdt", .data = reg_offset_data_kpss },
93 + { .compatible = "qcom,kpss-timer", .data = &match_data_apcs_tmr },
94 + { .compatible = "qcom,scss-timer", .data = &match_data_apcs_tmr },
95 + { .compatible = "qcom,kpss-wdt", .data = &match_data_kpss },
96 { },
97 };
98 MODULE_DEVICE_TABLE(of, qcom_wdt_of_table);