hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/orion_wdt.c
....@@ -35,7 +35,15 @@
3535 * Watchdog timer block registers.
3636 */
3737 #define TIMER_CTRL 0x0000
38
-#define TIMER_A370_STATUS 0x04
38
+#define TIMER1_FIXED_ENABLE_BIT BIT(12)
39
+#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
40
+#define TIMER1_ENABLE_BIT BIT(2)
41
+
42
+#define TIMER_A370_STATUS 0x0004
43
+#define WDT_A370_EXPIRED BIT(31)
44
+#define TIMER1_STATUS_BIT BIT(8)
45
+
46
+#define TIMER1_VAL_OFF 0x001c
3947
4048 #define WDT_MAX_CYCLE_COUNT 0xffffffff
4149
....@@ -43,11 +51,8 @@
4351 #define WDT_A370_RATIO_SHIFT 5
4452 #define WDT_A370_RATIO (1 << WDT_A370_RATIO_SHIFT)
4553
46
-#define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
47
-#define WDT_A370_EXPIRED BIT(31)
48
-
4954 static bool nowayout = WATCHDOG_NOWAYOUT;
50
-static int heartbeat = -1; /* module parameter (seconds) */
55
+static int heartbeat; /* module parameter (seconds) */
5156
5257 struct orion_watchdog;
5358
....@@ -158,6 +163,7 @@
158163 struct orion_watchdog *dev)
159164 {
160165 int ret;
166
+ u32 val;
161167
162168 dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
163169 if (IS_ERR(dev->clk))
....@@ -168,10 +174,9 @@
168174 return ret;
169175 }
170176
171
- /* Enable the fixed watchdog clock input */
172
- atomic_io_modify(dev->reg + TIMER_CTRL,
173
- WDT_AXP_FIXED_ENABLE_BIT,
174
- WDT_AXP_FIXED_ENABLE_BIT);
177
+ /* Fix the wdt and timer1 clock freqency to 25MHz */
178
+ val = WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT;
179
+ atomic_io_modify(dev->reg + TIMER_CTRL, val, val);
175180
176181 dev->clk_rate = clk_get_rate(dev->clk);
177182 return 0;
....@@ -183,6 +188,10 @@
183188 /* Reload watchdog duration */
184189 writel(dev->clk_rate * wdt_dev->timeout,
185190 dev->reg + dev->data->wdt_counter_offset);
191
+ if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
192
+ writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
193
+ dev->reg + TIMER1_VAL_OFF);
194
+
186195 return 0;
187196 }
188197
....@@ -194,13 +203,18 @@
194203 /* Set watchdog duration */
195204 writel(dev->clk_rate * wdt_dev->timeout,
196205 dev->reg + dev->data->wdt_counter_offset);
206
+ if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
207
+ writel(dev->clk_rate * (wdt_dev->timeout - wdt_dev->pretimeout),
208
+ dev->reg + TIMER1_VAL_OFF);
197209
198210 /* Clear the watchdog expiration bit */
199211 atomic_io_modify(dev->reg + TIMER_A370_STATUS, WDT_A370_EXPIRED, 0);
200212
201213 /* Enable watchdog timer */
202
- atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit,
203
- dev->data->wdt_enable_bit);
214
+ reg = dev->data->wdt_enable_bit;
215
+ if (dev->wdt.info->options & WDIOF_PRETIMEOUT)
216
+ reg |= TIMER1_ENABLE_BIT;
217
+ atomic_io_modify(dev->reg + TIMER_CTRL, reg, reg);
204218
205219 /* Enable reset on watchdog */
206220 reg = readl(dev->rstout);
....@@ -277,7 +291,7 @@
277291 static int armada375_stop(struct watchdog_device *wdt_dev)
278292 {
279293 struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
280
- u32 reg;
294
+ u32 reg, mask;
281295
282296 /* Disable reset on watchdog */
283297 atomic_io_modify(dev->rstout_mask, dev->data->rstout_mask_bit,
....@@ -287,7 +301,10 @@
287301 writel(reg, dev->rstout);
288302
289303 /* Disable watchdog timer */
290
- atomic_io_modify(dev->reg + TIMER_CTRL, dev->data->wdt_enable_bit, 0);
304
+ mask = dev->data->wdt_enable_bit;
305
+ if (wdt_dev->info->options & WDIOF_PRETIMEOUT)
306
+ mask |= TIMER1_ENABLE_BIT;
307
+ atomic_io_modify(dev->reg + TIMER_CTRL, mask, 0);
291308
292309 return 0;
293310 }
....@@ -349,14 +366,7 @@
349366 return readl(dev->reg + dev->data->wdt_counter_offset) / dev->clk_rate;
350367 }
351368
352
-static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev,
353
- unsigned int timeout)
354
-{
355
- wdt_dev->timeout = timeout;
356
- return 0;
357
-}
358
-
359
-static const struct watchdog_info orion_wdt_info = {
369
+static struct watchdog_info orion_wdt_info = {
360370 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
361371 .identity = "Orion Watchdog",
362372 };
....@@ -366,13 +376,22 @@
366376 .start = orion_wdt_start,
367377 .stop = orion_wdt_stop,
368378 .ping = orion_wdt_ping,
369
- .set_timeout = orion_wdt_set_timeout,
370379 .get_timeleft = orion_wdt_get_timeleft,
371380 };
372381
373382 static irqreturn_t orion_wdt_irq(int irq, void *devid)
374383 {
375384 panic("Watchdog Timeout");
385
+ return IRQ_HANDLED;
386
+}
387
+
388
+static irqreturn_t orion_wdt_pre_irq(int irq, void *devid)
389
+{
390
+ struct orion_watchdog *dev = devid;
391
+
392
+ atomic_io_modify(dev->reg + TIMER_A370_STATUS,
393
+ TIMER1_STATUS_BIT, 0);
394
+ watchdog_notify_pretimeout(&dev->wdt);
376395 return IRQ_HANDLED;
377396 }
378397
....@@ -502,8 +521,7 @@
502521 of_device_is_compatible(node, "marvell,armada-xp-wdt")) {
503522
504523 /* Dedicated RSTOUT register, can be requested. */
505
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
506
- dev->rstout = devm_ioremap_resource(&pdev->dev, res);
524
+ dev->rstout = devm_platform_ioremap_resource(pdev, 1);
507525 if (IS_ERR(dev->rstout))
508526 return PTR_ERR(dev->rstout);
509527
....@@ -511,8 +529,7 @@
511529 of_device_is_compatible(node, "marvell,armada-380-wdt")) {
512530
513531 /* Dedicated RSTOUT register, can be requested. */
514
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
515
- dev->rstout = devm_ioremap_resource(&pdev->dev, res);
532
+ dev->rstout = devm_platform_ioremap_resource(pdev, 1);
516533 if (IS_ERR(dev->rstout))
517534 return PTR_ERR(dev->rstout);
518535
....@@ -585,7 +602,7 @@
585602 set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
586603
587604 /* Request the IRQ only after the watchdog is disabled */
588
- irq = platform_get_irq(pdev, 0);
605
+ irq = platform_get_irq_optional(pdev, 0);
589606 if (irq > 0) {
590607 /*
591608 * Not all supported platforms specify an interrupt for the
....@@ -599,6 +616,19 @@
599616 }
600617 }
601618
619
+ /* Optional 2nd interrupt for pretimeout */
620
+ irq = platform_get_irq_optional(pdev, 1);
621
+ if (irq > 0) {
622
+ orion_wdt_info.options |= WDIOF_PRETIMEOUT;
623
+ ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
624
+ 0, pdev->name, dev);
625
+ if (ret < 0) {
626
+ dev_err(&pdev->dev, "failed to request IRQ\n");
627
+ goto disable_clk;
628
+ }
629
+ }
630
+
631
+
602632 watchdog_set_nowayout(&dev->wdt, nowayout);
603633 ret = watchdog_register_device(&dev->wdt);
604634 if (ret)