projects/linux·blob master · refs

624 lines · 15.4 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2019-2025 NVIDIA Corporation. All rights reserved.
4 */
5
6#include <linux/bitfield.h>
7#include <linux/clocksource.h>
8#include <linux/module.h>
9#include <linux/interrupt.h>
10#include <linux/io.h>
11#include <linux/of.h>
12#include <linux/platform_device.h>
13#include <linux/pm.h>
14#include <linux/watchdog.h>
15
16/* shared registers */
17#define TKETSC0 0x000
18#define TKETSC1 0x004
19#define TKEUSEC 0x008
20#define TKEOSC 0x00c
21
22#define TKEIE(x) (0x100 + ((x) * 4))
23#define TKEIE_WDT_MASK(x, y) ((y) << (16 + 4 * (x)))
24
25/* timer registers */
26#define TMRCR 0x000
27#define TMRCR_ENABLE BIT(31)
28#define TMRCR_PERIODIC BIT(30)
29#define TMRCR_PTV(x) ((x) & 0x0fffffff)
30
31#define TMRSR 0x004
32#define TMRSR_INTR_CLR BIT(30)
33#define TMRSR_PCV GENMASK(28, 0)
34
35#define TMRCSSR 0x008
36#define TMRCSSR_SRC_USEC (0 << 0)
37
38/* watchdog registers */
39#define WDTCR 0x000
40#define WDTCR_SYSTEM_POR_RESET_ENABLE BIT(16)
41#define WDTCR_SYSTEM_DEBUG_RESET_ENABLE BIT(15)
42#define WDTCR_REMOTE_INT_ENABLE BIT(14)
43#define WDTCR_LOCAL_FIQ_ENABLE BIT(13)
44#define WDTCR_LOCAL_INT_ENABLE BIT(12)
45#define WDTCR_PERIOD_MASK (0xff << 4)
46#define WDTCR_PERIOD(x) (((x) & 0xff) << 4)
47#define WDTCR_TIMER_SOURCE_MASK 0xf
48#define WDTCR_TIMER_SOURCE(x) ((x) & 0xf)
49
50#define WDTSR 0x004
51#define WDTSR_CURRENT_EXPIRATION_COUNT GENMASK(14, 12)
52
53#define WDTCMDR 0x008
54#define WDTCMDR_DISABLE_COUNTER BIT(1)
55#define WDTCMDR_START_COUNTER BIT(0)
56
57#define WDTUR 0x00c
58#define WDTUR_UNLOCK_PATTERN 0x0000c45a
59
60#define TEGRA186_KERNEL_WDT_TIMEOUT 120
61
62/* WDT security configuration registers */
63#define WDTSCR(x) (0xf02c + (x) * 4)
64#define WDTSCR_SEC_WEN BIT(28)
65#define WDTSCR_SEC_REN BIT(27)
66#define WDTSCR_SEC_G1W BIT(9)
67#define WDTSCR_SEC_G1R BIT(1)
68
69struct tegra186_timer_soc {
70 unsigned int num_timers;
71 unsigned int num_wdts;
72};
73
74struct tegra186_tmr {
75 struct tegra186_timer *parent;
76 void __iomem *regs;
77 unsigned int index;
78 unsigned int hwirq;
79};
80
81struct tegra186_wdt {
82 struct watchdog_device base;
83
84 void __iomem *regs;
85 unsigned int index;
86 bool locked;
87 bool is_kernel_wdt;
88
89 struct tegra186_tmr *tmr;
90};
91
92static inline struct tegra186_wdt *to_tegra186_wdt(struct watchdog_device *wdd)
93{
94 return container_of(wdd, struct tegra186_wdt, base);
95}
96
97struct tegra186_timer {
98 const struct tegra186_timer_soc *soc;
99 struct device *dev;
100 void __iomem *regs;
101
102 struct tegra186_wdt **wdts;
103 struct clocksource usec;
104 struct clocksource tsc;
105 struct clocksource osc;
106};
107
108static void tmr_writel(struct tegra186_tmr *tmr, u32 value, unsigned int offset)
109{
110 writel_relaxed(value, tmr->regs + offset);
111}
112
113static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset)
114{
115 writel_relaxed(value, wdt->regs + offset);
116}
117
118static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset)
119{
120 return readl_relaxed(wdt->regs + offset);
121}
122
123static struct tegra186_tmr *tegra186_tmr_create(struct tegra186_timer *tegra,
124 unsigned int index)
125{
126 unsigned int offset = 0x10000 + index * 0x10000;
127 struct tegra186_tmr *tmr;
128
129 tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL);
130 if (!tmr)
131 return ERR_PTR(-ENOMEM);
132
133 tmr->parent = tegra;
134 tmr->regs = tegra->regs + offset;
135 tmr->index = index;
136 tmr->hwirq = 0;
137
138 return tmr;
139}
140
141static const struct watchdog_info tegra186_wdt_info = {
142 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
143 .identity = "NVIDIA Tegra186 WDT",
144};
145
146static void tegra186_wdt_disable(struct tegra186_wdt *wdt)
147{
148 /* unlock and disable the watchdog */
149 wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
150 wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
151
152 /* disable timer */
153 tmr_writel(wdt->tmr, 0, TMRCR);
154}
155
156static void tegra186_wdt_enable(struct tegra186_wdt *wdt)
157{
158 struct tegra186_timer *tegra = wdt->tmr->parent;
159 u32 value;
160
161 /* unmask hardware IRQ, this may have been lost across powergate */
162 value = readl(tegra->regs + TKEIE(wdt->tmr->hwirq));
163 value |= TKEIE_WDT_MASK(wdt->index, 1);
164 writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
165
166 /* clear interrupt */
167 tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
168
169 /* select microsecond source */
170 tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
171
172 /* configure timer (system reset happens on the fifth expiration) */
173 value = TMRCR_PTV(wdt->base.timeout * (USEC_PER_SEC / 5)) |
174 TMRCR_PERIODIC | TMRCR_ENABLE;
175 tmr_writel(wdt->tmr, value, TMRCR);
176
177 if (!wdt->locked) {
178 value = wdt_readl(wdt, WDTCR);
179
180 /* select the proper timer source */
181 value &= ~WDTCR_TIMER_SOURCE_MASK;
182 value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
183
184 /* single timer period since that's already configured */
185 value &= ~WDTCR_PERIOD_MASK;
186 value |= WDTCR_PERIOD(1);
187
188 /* enable local interrupt for kernel watchdog */
189 if (wdt->is_kernel_wdt)
190 value |= WDTCR_LOCAL_INT_ENABLE;
191
192 /* enable system POR reset */
193 value |= WDTCR_SYSTEM_POR_RESET_ENABLE;
194
195 wdt_writel(wdt, value, WDTCR);
196 }
197
198 wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR);
199}
200
201static int tegra186_wdt_start(struct watchdog_device *wdd)
202{
203 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
204
205 tegra186_wdt_enable(wdt);
206
207 return 0;
208}
209
210static int tegra186_wdt_stop(struct watchdog_device *wdd)
211{
212 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
213
214 tegra186_wdt_disable(wdt);
215
216 return 0;
217}
218
219static int tegra186_wdt_ping(struct watchdog_device *wdd)
220{
221 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
222
223 tegra186_wdt_disable(wdt);
224 tegra186_wdt_enable(wdt);
225
226 return 0;
227}
228
229static irqreturn_t tegra186_wdt_irq(int irq, void *data)
230{
231 struct tegra186_wdt *wdt = data;
232
233 tegra186_wdt_disable(wdt);
234 tegra186_wdt_enable(wdt);
235
236 return IRQ_HANDLED;
237}
238
239static int tegra186_wdt_set_timeout(struct watchdog_device *wdd,
240 unsigned int timeout)
241{
242 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
243
244 if (watchdog_active(&wdt->base))
245 tegra186_wdt_disable(wdt);
246
247 wdt->base.timeout = timeout;
248
249 if (watchdog_active(&wdt->base))
250 tegra186_wdt_enable(wdt);
251
252 return 0;
253}
254
255static unsigned int tegra186_wdt_get_timeleft(struct watchdog_device *wdd)
256{
257 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
258 u32 expiration, val;
259 u32 timeleft;
260
261 if (!watchdog_active(&wdt->base)) {
262 /* return zero if the watchdog timer is not activated. */
263 return 0;
264 }
265
266 /*
267 * Reset occurs on the fifth expiration of the
268 * watchdog timer and so when the watchdog timer is configured,
269 * the actual value programmed into the counter is 1/5 of the
270 * timeout value. Once the counter reaches 0, expiration count
271 * will be increased by 1 and the down counter restarts.
272 * Hence to get the time left before system reset we must
273 * combine 2 parts:
274 * 1. value of the current down counter
275 * 2. (number of counter expirations remaining) * (timeout/5)
276 */
277
278 /* Get the current number of counter expirations. Should be a
279 * value between 0 and 4
280 */
281 val = readl_relaxed(wdt->regs + WDTSR);
282 expiration = FIELD_GET(WDTSR_CURRENT_EXPIRATION_COUNT, val);
283 if (WARN_ON_ONCE(expiration > 4))
284 return 0;
285
286 /* Get the current counter value in microsecond. */
287 val = readl_relaxed(wdt->tmr->regs + TMRSR);
288 timeleft = FIELD_GET(TMRSR_PCV, val);
289
290 /*
291 * Calculate the time remaining by adding the time for the
292 * counter value to the time of the counter expirations that
293 * remain.
294 * Note: Since wdt->base.timeout is bound to 255, the maximum
295 * value added to timeleft is
296 * 255 * (1,000,000 / 5) * 4
297 * = 255 * 200,000 * 4
298 * = 204,000,000
299 * TMRSR_PCV is a 29-bit field.
300 * Its maximum value is 0x1fffffff = 536,870,911.
301 * 204,000,000 + 536,870,911 = 740,870,911 = 0x2C28CAFF.
302 * timeleft can therefore not overflow, and 64-bit calculations
303 * are not necessary.
304 */
305 timeleft += (wdt->base.timeout * (USEC_PER_SEC / 5)) * (4 - expiration);
306
307 /*
308 * Convert the current counter value to seconds,
309 * rounding to the nearest second.
310 */
311 timeleft = DIV_ROUND_CLOSEST(timeleft, USEC_PER_SEC);
312
313 return timeleft;
314}
315
316static const struct watchdog_ops tegra186_wdt_ops = {
317 .owner = THIS_MODULE,
318 .start = tegra186_wdt_start,
319 .stop = tegra186_wdt_stop,
320 .ping = tegra186_wdt_ping,
321 .set_timeout = tegra186_wdt_set_timeout,
322 .get_timeleft = tegra186_wdt_get_timeleft,
323};
324
325static bool tegra186_wdt_is_accessible(struct tegra186_timer *tegra, unsigned int index)
326{
327 u32 value;
328
329 value = readl_relaxed(tegra->regs + WDTSCR(index));
330
331 /* Check OS write access if write blocking is enabled. */
332 if ((value & WDTSCR_SEC_WEN) && !(value & WDTSCR_SEC_G1W))
333 return false;
334
335 /* Check OS read access if read blocking is enabled. */
336 if ((value & WDTSCR_SEC_REN) && !(value & WDTSCR_SEC_G1R))
337 return false;
338
339 return true;
340}
341
342static struct tegra186_wdt *tegra186_wdt_create(struct tegra186_timer *tegra,
343 unsigned int index)
344{
345 unsigned int offset = 0x10000, source;
346 struct tegra186_wdt *wdt;
347 u32 value;
348 int err;
349
350 offset += tegra->soc->num_timers * 0x10000 + index * 0x10000;
351
352 wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL);
353 if (!wdt)
354 return ERR_PTR(-ENOMEM);
355
356 wdt->regs = tegra->regs + offset;
357 wdt->index = index;
358
359 /* read the watchdog configuration since it might be locked down */
360 value = wdt_readl(wdt, WDTCR);
361
362 if (value & WDTCR_LOCAL_INT_ENABLE)
363 wdt->locked = true;
364
365 source = value & WDTCR_TIMER_SOURCE_MASK;
366
367 wdt->tmr = tegra186_tmr_create(tegra, source);
368 if (IS_ERR(wdt->tmr))
369 return ERR_CAST(wdt->tmr);
370
371 wdt->base.info = &tegra186_wdt_info;
372 wdt->base.ops = &tegra186_wdt_ops;
373 wdt->base.min_timeout = 1;
374 wdt->base.max_timeout = 255;
375 wdt->base.parent = tegra->dev;
376
377 err = watchdog_init_timeout(&wdt->base, 5, tegra->dev);
378 if (err < 0)
379 return ERR_PTR(err);
380
381 return wdt;
382}
383
384static u64 tegra186_timer_tsc_read(struct clocksource *cs)
385{
386 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
387 tsc);
388 u32 hi, lo, ss;
389
390 hi = readl_relaxed(tegra->regs + TKETSC1);
391
392 /*
393 * The 56-bit value of the TSC is spread across two registers that are
394 * not synchronized. In order to read them atomically, ensure that the
395 * high 24 bits match before and after reading the low 32 bits.
396 */
397 do {
398 /* snapshot the high 24 bits */
399 ss = hi;
400
401 lo = readl_relaxed(tegra->regs + TKETSC0);
402 hi = readl_relaxed(tegra->regs + TKETSC1);
403 } while (hi != ss);
404
405 return (u64)hi << 32 | lo;
406}
407
408static int tegra186_timer_tsc_init(struct tegra186_timer *tegra)
409{
410 tegra->tsc.name = "tsc";
411 tegra->tsc.rating = 300;
412 tegra->tsc.read = tegra186_timer_tsc_read;
413 tegra->tsc.mask = CLOCKSOURCE_MASK(56);
414 tegra->tsc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
415 tegra->tsc.owner = THIS_MODULE;
416
417 return clocksource_register_hz(&tegra->tsc, 31250000);
418}
419
420static u64 tegra186_timer_osc_read(struct clocksource *cs)
421{
422 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
423 osc);
424
425 return readl_relaxed(tegra->regs + TKEOSC);
426}
427
428static int tegra186_timer_osc_init(struct tegra186_timer *tegra)
429{
430 tegra->osc.name = "osc";
431 tegra->osc.rating = 300;
432 tegra->osc.read = tegra186_timer_osc_read;
433 tegra->osc.mask = CLOCKSOURCE_MASK(32);
434 tegra->osc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
435 tegra->osc.owner = THIS_MODULE;
436
437 return clocksource_register_hz(&tegra->osc, 38400000);
438}
439
440static u64 tegra186_timer_usec_read(struct clocksource *cs)
441{
442 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
443 usec);
444
445 return readl_relaxed(tegra->regs + TKEUSEC);
446}
447
448static int tegra186_timer_usec_init(struct tegra186_timer *tegra)
449{
450 tegra->usec.name = "usec";
451 tegra->usec.rating = 300;
452 tegra->usec.read = tegra186_timer_usec_read;
453 tegra->usec.mask = CLOCKSOURCE_MASK(32);
454 tegra->usec.flags = CLOCK_SOURCE_IS_CONTINUOUS;
455 tegra->usec.owner = THIS_MODULE;
456
457 return clocksource_register_hz(&tegra->usec, USEC_PER_SEC);
458}
459
460static int tegra186_timer_probe(struct platform_device *pdev)
461{
462 struct tegra186_wdt *kernel_wdt = NULL;
463 struct device *dev = &pdev->dev;
464 struct tegra186_timer *tegra;
465 unsigned int i;
466 int irq;
467 int err;
468
469 tegra = devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL);
470 if (!tegra)
471 return -ENOMEM;
472
473 tegra->soc = of_device_get_match_data(dev);
474 dev_set_drvdata(dev, tegra);
475 tegra->dev = dev;
476
477 tegra->regs = devm_platform_ioremap_resource(pdev, 0);
478 if (IS_ERR(tegra->regs))
479 return PTR_ERR(tegra->regs);
480
481 err = platform_get_irq(pdev, 0);
482 if (err < 0)
483 return err;
484
485 irq = err;
486
487 tegra->wdts = devm_kcalloc(dev, tegra->soc->num_wdts, sizeof(*tegra->wdts), GFP_KERNEL);
488 if (!tegra->wdts)
489 return -ENOMEM;
490
491 for (i = 0; i < tegra->soc->num_wdts; i++) {
492 if (!tegra186_wdt_is_accessible(tegra, i)) {
493 dev_warn(dev, "WDT%u is not accessible\n", i);
494 continue;
495 }
496
497 tegra->wdts[i] = tegra186_wdt_create(tegra, i);
498 if (IS_ERR(tegra->wdts[i]))
499 return dev_err_probe(dev, PTR_ERR(tegra->wdts[i]),
500 "failed to create WDT%u\n", i);
501
502 /* Reserve the first accessible WDT for the Kernel. */
503 if (!kernel_wdt) {
504 kernel_wdt = tegra->wdts[i];
505 kernel_wdt->is_kernel_wdt = true;
506 } else {
507 err = devm_watchdog_register_device(dev, &tegra->wdts[i]->base);
508 if (err < 0)
509 return dev_err_probe(dev, err,
510 "failed to register WDT%u\n", i);
511 }
512 }
513
514 err = tegra186_timer_tsc_init(tegra);
515 if (err < 0) {
516 dev_err(dev, "failed to register TSC counter: %d\n", err);
517 return err;
518 }
519
520 err = tegra186_timer_osc_init(tegra);
521 if (err < 0) {
522 dev_err(dev, "failed to register OSC counter: %d\n", err);
523 goto unregister_tsc;
524 }
525
526 err = tegra186_timer_usec_init(tegra);
527 if (err < 0) {
528 dev_err(dev, "failed to register USEC counter: %d\n", err);
529 goto unregister_osc;
530 }
531
532 if (kernel_wdt) {
533 err = devm_request_irq(dev, irq, tegra186_wdt_irq, 0,
534 dev_name(dev), kernel_wdt);
535 if (err < 0)
536 goto unregister_usec;
537
538 tegra186_wdt_set_timeout(&kernel_wdt->base, TEGRA186_KERNEL_WDT_TIMEOUT);
539 tegra186_wdt_enable(kernel_wdt);
540 }
541
542 return 0;
543
544unregister_usec:
545 clocksource_unregister(&tegra->usec);
546unregister_osc:
547 clocksource_unregister(&tegra->osc);
548unregister_tsc:
549 clocksource_unregister(&tegra->tsc);
550 return err;
551}
552
553static void tegra186_timer_remove(struct platform_device *pdev)
554{
555 struct tegra186_timer *tegra = platform_get_drvdata(pdev);
556
557 clocksource_unregister(&tegra->usec);
558 clocksource_unregister(&tegra->osc);
559 clocksource_unregister(&tegra->tsc);
560}
561
562static int __maybe_unused tegra186_timer_suspend(struct device *dev)
563{
564 struct tegra186_timer *tegra = dev_get_drvdata(dev);
565 unsigned int i;
566
567 for (i = 0; i < tegra->soc->num_wdts; i++) {
568 struct tegra186_wdt *wdt = tegra->wdts[i];
569
570 if (wdt && (wdt->is_kernel_wdt || watchdog_active(&wdt->base)))
571 tegra186_wdt_disable(wdt);
572 }
573
574 return 0;
575}
576
577static int __maybe_unused tegra186_timer_resume(struct device *dev)
578{
579 struct tegra186_timer *tegra = dev_get_drvdata(dev);
580 unsigned int i;
581
582 for (i = 0; i < tegra->soc->num_wdts; i++) {
583 struct tegra186_wdt *wdt = tegra->wdts[i];
584
585 if (wdt && (wdt->is_kernel_wdt || watchdog_active(&wdt->base)))
586 tegra186_wdt_enable(wdt);
587 }
588
589 return 0;
590}
591
592static SIMPLE_DEV_PM_OPS(tegra186_timer_pm_ops, tegra186_timer_suspend,
593 tegra186_timer_resume);
594
595static const struct tegra186_timer_soc tegra186_timer = {
596 .num_timers = 10,
597 .num_wdts = 2,
598};
599
600static const struct tegra186_timer_soc tegra234_timer = {
601 .num_timers = 16,
602 .num_wdts = 2,
603};
604
605static const struct of_device_id tegra186_timer_of_match[] = {
606 { .compatible = "nvidia,tegra186-timer", .data = &tegra186_timer },
607 { .compatible = "nvidia,tegra234-timer", .data = &tegra234_timer },
608 { }
609};
610MODULE_DEVICE_TABLE(of, tegra186_timer_of_match);
611
612static struct platform_driver tegra186_wdt_driver = {
613 .driver = {
614 .name = "tegra186-timer",
615 .pm = &tegra186_timer_pm_ops,
616 .of_match_table = tegra186_timer_of_match,
617 },
618 .probe = tegra186_timer_probe,
619 .remove = tegra186_timer_remove,
620};
621module_platform_driver(tegra186_wdt_driver);
622
623MODULE_AUTHOR("Thierry Reding <[email protected]>");
624MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver");