hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/watchdog/intel-mid_wdt.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * intel-mid_wdt: generic Intel MID SCU watchdog driver
34 *
....@@ -6,10 +7,6 @@
67 *
78 * Copyright (C) 2014 Intel Corporation. All rights reserved.
89 * Contact: David Cohen <david.a.cohen@linux.intel.com>
9
- *
10
- * This program is free software; you can redistribute it and/or
11
- * modify it under the terms of version 2 of the GNU General
12
- * Public License as published by the Free Software Foundation.
1310 */
1411
1512 #include <linux/interrupt.h>
....@@ -36,14 +33,24 @@
3633 SCU_WATCHDOG_KEEPALIVE,
3734 };
3835
39
-static inline int wdt_command(int sub, u32 *in, int inlen)
36
+struct mid_wdt {
37
+ struct watchdog_device wd;
38
+ struct device *dev;
39
+ struct intel_scu_ipc_dev *scu;
40
+};
41
+
42
+static inline int
43
+wdt_command(struct mid_wdt *mid, int sub, const void *in, size_t inlen, size_t size)
4044 {
41
- return intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0);
45
+ struct intel_scu_ipc_dev *scu = mid->scu;
46
+
47
+ return intel_scu_ipc_dev_command_with_size(scu, IPC_WATCHDOG, sub, in,
48
+ inlen, size, NULL, 0);
4249 }
4350
4451 static int wdt_start(struct watchdog_device *wd)
4552 {
46
- struct device *dev = watchdog_get_drvdata(wd);
53
+ struct mid_wdt *mid = watchdog_get_drvdata(wd);
4754 int ret, in_size;
4855 int timeout = wd->timeout;
4956 struct ipc_wd_start {
....@@ -52,38 +59,41 @@
5259 } ipc_wd_start = { timeout - MID_WDT_PRETIMEOUT, timeout };
5360
5461 /*
55
- * SCU expects the input size for watchdog IPC to
56
- * be based on 4 bytes
62
+ * SCU expects the input size for watchdog IPC to be 2 which is the
63
+ * size of the structure in dwords. SCU IPC normally takes bytes
64
+ * but this is a special case where we specify size to be different
65
+ * than inlen.
5766 */
5867 in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4);
5968
60
- ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size);
69
+ ret = wdt_command(mid, SCU_WATCHDOG_START, &ipc_wd_start,
70
+ sizeof(ipc_wd_start), in_size);
6171 if (ret)
62
- dev_crit(dev, "error starting watchdog: %d\n", ret);
72
+ dev_crit(mid->dev, "error starting watchdog: %d\n", ret);
6373
6474 return ret;
6575 }
6676
6777 static int wdt_ping(struct watchdog_device *wd)
6878 {
69
- struct device *dev = watchdog_get_drvdata(wd);
79
+ struct mid_wdt *mid = watchdog_get_drvdata(wd);
7080 int ret;
7181
72
- ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0);
82
+ ret = wdt_command(mid, SCU_WATCHDOG_KEEPALIVE, NULL, 0, 0);
7383 if (ret)
74
- dev_crit(dev, "Error executing keepalive: %d\n", ret);
84
+ dev_crit(mid->dev, "Error executing keepalive: %d\n", ret);
7585
7686 return ret;
7787 }
7888
7989 static int wdt_stop(struct watchdog_device *wd)
8090 {
81
- struct device *dev = watchdog_get_drvdata(wd);
91
+ struct mid_wdt *mid = watchdog_get_drvdata(wd);
8292 int ret;
8393
84
- ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0);
94
+ ret = wdt_command(mid, SCU_WATCHDOG_STOP, NULL, 0, 0);
8595 if (ret)
86
- dev_crit(dev, "Error stopping watchdog: %d\n", ret);
96
+ dev_crit(mid->dev, "Error stopping watchdog: %d\n", ret);
8797
8898 return ret;
8999 }
....@@ -110,12 +120,14 @@
110120
111121 static int mid_wdt_probe(struct platform_device *pdev)
112122 {
123
+ struct device *dev = &pdev->dev;
113124 struct watchdog_device *wdt_dev;
114
- struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
125
+ struct intel_mid_wdt_pdata *pdata = dev->platform_data;
126
+ struct mid_wdt *mid;
115127 int ret;
116128
117129 if (!pdata) {
118
- dev_err(&pdev->dev, "missing platform data\n");
130
+ dev_err(dev, "missing platform data\n");
119131 return -EINVAL;
120132 }
121133
....@@ -125,25 +137,32 @@
125137 return ret;
126138 }
127139
128
- wdt_dev = devm_kzalloc(&pdev->dev, sizeof(*wdt_dev), GFP_KERNEL);
129
- if (!wdt_dev)
140
+ mid = devm_kzalloc(dev, sizeof(*mid), GFP_KERNEL);
141
+ if (!mid)
130142 return -ENOMEM;
143
+
144
+ mid->dev = dev;
145
+ wdt_dev = &mid->wd;
131146
132147 wdt_dev->info = &mid_wdt_info;
133148 wdt_dev->ops = &mid_wdt_ops;
134149 wdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN;
135150 wdt_dev->max_timeout = MID_WDT_TIMEOUT_MAX;
136151 wdt_dev->timeout = MID_WDT_DEFAULT_TIMEOUT;
137
- wdt_dev->parent = &pdev->dev;
152
+ wdt_dev->parent = dev;
138153
139
- watchdog_set_drvdata(wdt_dev, &pdev->dev);
154
+ watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT);
155
+ watchdog_set_drvdata(wdt_dev, mid);
140156
141
- ret = devm_request_irq(&pdev->dev, pdata->irq, mid_wdt_irq,
157
+ mid->scu = devm_intel_scu_ipc_dev_get(dev);
158
+ if (!mid->scu)
159
+ return -EPROBE_DEFER;
160
+
161
+ ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq,
142162 IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog",
143163 wdt_dev);
144164 if (ret) {
145
- dev_err(&pdev->dev, "error requesting warning irq %d\n",
146
- pdata->irq);
165
+ dev_err(dev, "error requesting warning irq %d\n", pdata->irq);
147166 return ret;
148167 }
149168
....@@ -163,13 +182,11 @@
163182 /* Make sure the watchdog is serviced */
164183 set_bit(WDOG_HW_RUNNING, &wdt_dev->status);
165184
166
- ret = devm_watchdog_register_device(&pdev->dev, wdt_dev);
167
- if (ret) {
168
- dev_err(&pdev->dev, "error registering watchdog device\n");
185
+ ret = devm_watchdog_register_device(dev, wdt_dev);
186
+ if (ret)
169187 return ret;
170
- }
171188
172
- dev_info(&pdev->dev, "Intel MID watchdog device probed\n");
189
+ dev_info(dev, "Intel MID watchdog device probed\n");
173190
174191 return 0;
175192 }
....@@ -186,3 +203,4 @@
186203 MODULE_AUTHOR("David Cohen <david.a.cohen@linux.intel.com>");
187204 MODULE_DESCRIPTION("Watchdog Driver for Intel MID platform");
188205 MODULE_LICENSE("GPL");
206
+MODULE_ALIAS("platform:intel_mid_wdt");