1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2019-2020 NVIDIA Corporation. All rights reserved.
6 #include <linux/clocksource.h>
7 #include <linux/module.h>
8 #include <linux/interrupt.h>
11 #include <linux/platform_device.h>
13 #include <linux/watchdog.h>
15 /* shared registers */
21 #define TKEIE(x) (0x100 + ((x) * 4))
22 #define TKEIE_WDT_MASK(x, y) ((y) << (16 + 4 * (x)))
26 #define TMRCR_ENABLE BIT(31)
27 #define TMRCR_PERIODIC BIT(30)
28 #define TMRCR_PTV(x) ((x) & 0x0fffffff)
31 #define TMRSR_INTR_CLR BIT(30)
34 #define TMRCSSR_SRC_USEC (0 << 0)
36 /* watchdog registers */
38 #define WDTCR_SYSTEM_POR_RESET_ENABLE BIT(16)
39 #define WDTCR_SYSTEM_DEBUG_RESET_ENABLE BIT(15)
40 #define WDTCR_REMOTE_INT_ENABLE BIT(14)
41 #define WDTCR_LOCAL_FIQ_ENABLE BIT(13)
42 #define WDTCR_LOCAL_INT_ENABLE BIT(12)
43 #define WDTCR_PERIOD_MASK (0xff << 4)
44 #define WDTCR_PERIOD(x) (((x) & 0xff) << 4)
45 #define WDTCR_TIMER_SOURCE_MASK 0xf
46 #define WDTCR_TIMER_SOURCE(x) ((x) & 0xf)
49 #define WDTCMDR_DISABLE_COUNTER BIT(1)
50 #define WDTCMDR_START_COUNTER BIT(0)
53 #define WDTUR_UNLOCK_PATTERN 0x0000c45a
55 struct tegra186_timer_soc {
56 unsigned int num_timers;
57 unsigned int num_wdts;
61 struct tegra186_timer *parent;
68 struct watchdog_device base;
74 struct tegra186_tmr *tmr;
77 static inline struct tegra186_wdt *to_tegra186_wdt(struct watchdog_device *wdd)
79 return container_of(wdd, struct tegra186_wdt, base);
82 struct tegra186_timer {
83 const struct tegra186_timer_soc *soc;
87 struct tegra186_wdt *wdt;
88 struct clocksource usec;
89 struct clocksource tsc;
90 struct clocksource osc;
93 static void tmr_writel(struct tegra186_tmr *tmr, u32 value, unsigned int offset)
95 writel_relaxed(value, tmr->regs + offset);
98 static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset)
100 writel_relaxed(value, wdt->regs + offset);
103 static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset)
105 return readl_relaxed(wdt->regs + offset);
108 static struct tegra186_tmr *tegra186_tmr_create(struct tegra186_timer *tegra,
111 unsigned int offset = 0x10000 + index * 0x10000;
112 struct tegra186_tmr *tmr;
114 tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL);
116 return ERR_PTR(-ENOMEM);
119 tmr->regs = tegra->regs + offset;
126 static const struct watchdog_info tegra186_wdt_info = {
127 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
128 .identity = "NVIDIA Tegra186 WDT",
131 static void tegra186_wdt_disable(struct tegra186_wdt *wdt)
133 /* unlock and disable the watchdog */
134 wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
135 wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
138 tmr_writel(wdt->tmr, 0, TMRCR);
141 static void tegra186_wdt_enable(struct tegra186_wdt *wdt)
143 struct tegra186_timer *tegra = wdt->tmr->parent;
146 /* unmask hardware IRQ, this may have been lost across powergate */
147 value = TKEIE_WDT_MASK(wdt->index, 1);
148 writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
150 /* clear interrupt */
151 tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
153 /* select microsecond source */
154 tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
156 /* configure timer (system reset happens on the fifth expiration) */
157 value = TMRCR_PTV(wdt->base.timeout * USEC_PER_SEC / 5) |
158 TMRCR_PERIODIC | TMRCR_ENABLE;
159 tmr_writel(wdt->tmr, value, TMRCR);
162 value = wdt_readl(wdt, WDTCR);
164 /* select the proper timer source */
165 value &= ~WDTCR_TIMER_SOURCE_MASK;
166 value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
168 /* single timer period since that's already configured */
169 value &= ~WDTCR_PERIOD_MASK;
170 value |= WDTCR_PERIOD(1);
172 /* enable local interrupt for WDT petting */
173 value |= WDTCR_LOCAL_INT_ENABLE;
175 /* enable local FIQ and remote interrupt for debug dump */
177 value |= WDTCR_REMOTE_INT_ENABLE |
178 WDTCR_LOCAL_FIQ_ENABLE;
180 /* enable system debug reset (doesn't properly reboot) */
182 value |= WDTCR_SYSTEM_DEBUG_RESET_ENABLE;
184 /* enable system POR reset */
185 value |= WDTCR_SYSTEM_POR_RESET_ENABLE;
187 wdt_writel(wdt, value, WDTCR);
190 wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR);
193 static int tegra186_wdt_start(struct watchdog_device *wdd)
195 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
197 tegra186_wdt_enable(wdt);
202 static int tegra186_wdt_stop(struct watchdog_device *wdd)
204 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
206 tegra186_wdt_disable(wdt);
211 static int tegra186_wdt_ping(struct watchdog_device *wdd)
213 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
215 tegra186_wdt_disable(wdt);
216 tegra186_wdt_enable(wdt);
221 static int tegra186_wdt_set_timeout(struct watchdog_device *wdd,
222 unsigned int timeout)
224 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
226 if (watchdog_active(&wdt->base))
227 tegra186_wdt_disable(wdt);
229 wdt->base.timeout = timeout;
231 if (watchdog_active(&wdt->base))
232 tegra186_wdt_enable(wdt);
237 static const struct watchdog_ops tegra186_wdt_ops = {
238 .owner = THIS_MODULE,
239 .start = tegra186_wdt_start,
240 .stop = tegra186_wdt_stop,
241 .ping = tegra186_wdt_ping,
242 .set_timeout = tegra186_wdt_set_timeout,
245 static struct tegra186_wdt *tegra186_wdt_create(struct tegra186_timer *tegra,
248 unsigned int offset = 0x10000, source;
249 struct tegra186_wdt *wdt;
253 offset += tegra->soc->num_timers * 0x10000 + index * 0x10000;
255 wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL);
257 return ERR_PTR(-ENOMEM);
259 wdt->regs = tegra->regs + offset;
262 /* read the watchdog configuration since it might be locked down */
263 value = wdt_readl(wdt, WDTCR);
265 if (value & WDTCR_LOCAL_INT_ENABLE)
268 source = value & WDTCR_TIMER_SOURCE_MASK;
270 wdt->tmr = tegra186_tmr_create(tegra, source);
271 if (IS_ERR(wdt->tmr))
272 return ERR_CAST(wdt->tmr);
274 wdt->base.info = &tegra186_wdt_info;
275 wdt->base.ops = &tegra186_wdt_ops;
276 wdt->base.min_timeout = 1;
277 wdt->base.max_timeout = 255;
278 wdt->base.parent = tegra->dev;
280 err = watchdog_init_timeout(&wdt->base, 5, tegra->dev);
282 dev_err(tegra->dev, "failed to initialize timeout: %d\n", err);
286 err = devm_watchdog_register_device(tegra->dev, &wdt->base);
288 dev_err(tegra->dev, "failed to register WDT: %d\n", err);
295 static u64 tegra186_timer_tsc_read(struct clocksource *cs)
297 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
301 hi = readl_relaxed(tegra->regs + TKETSC1);
304 * The 56-bit value of the TSC is spread across two registers that are
305 * not synchronized. In order to read them atomically, ensure that the
306 * high 24 bits match before and after reading the low 32 bits.
309 /* snapshot the high 24 bits */
312 lo = readl_relaxed(tegra->regs + TKETSC0);
313 hi = readl_relaxed(tegra->regs + TKETSC1);
316 return (u64)hi << 32 | lo;
319 static int tegra186_timer_tsc_init(struct tegra186_timer *tegra)
321 tegra->tsc.name = "tsc";
322 tegra->tsc.rating = 300;
323 tegra->tsc.read = tegra186_timer_tsc_read;
324 tegra->tsc.mask = CLOCKSOURCE_MASK(56);
325 tegra->tsc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
327 return clocksource_register_hz(&tegra->tsc, 31250000);
330 static u64 tegra186_timer_osc_read(struct clocksource *cs)
332 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
335 return readl_relaxed(tegra->regs + TKEOSC);
338 static int tegra186_timer_osc_init(struct tegra186_timer *tegra)
340 tegra->osc.name = "osc";
341 tegra->osc.rating = 300;
342 tegra->osc.read = tegra186_timer_osc_read;
343 tegra->osc.mask = CLOCKSOURCE_MASK(32);
344 tegra->osc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
346 return clocksource_register_hz(&tegra->osc, 38400000);
349 static u64 tegra186_timer_usec_read(struct clocksource *cs)
351 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
354 return readl_relaxed(tegra->regs + TKEUSEC);
357 static int tegra186_timer_usec_init(struct tegra186_timer *tegra)
359 tegra->usec.name = "usec";
360 tegra->usec.rating = 300;
361 tegra->usec.read = tegra186_timer_usec_read;
362 tegra->usec.mask = CLOCKSOURCE_MASK(32);
363 tegra->usec.flags = CLOCK_SOURCE_IS_CONTINUOUS;
365 return clocksource_register_hz(&tegra->usec, USEC_PER_SEC);
368 static irqreturn_t tegra186_timer_irq(int irq, void *data)
370 struct tegra186_timer *tegra = data;
372 if (watchdog_active(&tegra->wdt->base)) {
373 tegra186_wdt_disable(tegra->wdt);
374 tegra186_wdt_enable(tegra->wdt);
380 static int tegra186_timer_probe(struct platform_device *pdev)
382 struct device *dev = &pdev->dev;
383 struct tegra186_timer *tegra;
387 tegra = devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL);
391 tegra->soc = of_device_get_match_data(dev);
392 dev_set_drvdata(dev, tegra);
395 tegra->regs = devm_platform_ioremap_resource(pdev, 0);
396 if (IS_ERR(tegra->regs))
397 return PTR_ERR(tegra->regs);
399 err = platform_get_irq(pdev, 0);
405 /* create a watchdog using a preconfigured timer */
406 tegra->wdt = tegra186_wdt_create(tegra, 0);
407 if (IS_ERR(tegra->wdt)) {
408 err = PTR_ERR(tegra->wdt);
409 dev_err(dev, "failed to create WDT: %d\n", err);
413 err = tegra186_timer_tsc_init(tegra);
415 dev_err(dev, "failed to register TSC counter: %d\n", err);
419 err = tegra186_timer_osc_init(tegra);
421 dev_err(dev, "failed to register OSC counter: %d\n", err);
425 err = tegra186_timer_usec_init(tegra);
427 dev_err(dev, "failed to register USEC counter: %d\n", err);
431 err = devm_request_irq(dev, irq, tegra186_timer_irq, 0,
432 "tegra186-timer", tegra);
434 dev_err(dev, "failed to request IRQ#%u: %d\n", irq, err);
435 goto unregister_usec;
441 clocksource_unregister(&tegra->usec);
443 clocksource_unregister(&tegra->osc);
445 clocksource_unregister(&tegra->tsc);
449 static void tegra186_timer_remove(struct platform_device *pdev)
451 struct tegra186_timer *tegra = platform_get_drvdata(pdev);
453 clocksource_unregister(&tegra->usec);
454 clocksource_unregister(&tegra->osc);
455 clocksource_unregister(&tegra->tsc);
458 static int __maybe_unused tegra186_timer_suspend(struct device *dev)
460 struct tegra186_timer *tegra = dev_get_drvdata(dev);
462 if (watchdog_active(&tegra->wdt->base))
463 tegra186_wdt_disable(tegra->wdt);
468 static int __maybe_unused tegra186_timer_resume(struct device *dev)
470 struct tegra186_timer *tegra = dev_get_drvdata(dev);
472 if (watchdog_active(&tegra->wdt->base))
473 tegra186_wdt_enable(tegra->wdt);
478 static SIMPLE_DEV_PM_OPS(tegra186_timer_pm_ops, tegra186_timer_suspend,
479 tegra186_timer_resume);
481 static const struct tegra186_timer_soc tegra186_timer = {
486 static const struct tegra186_timer_soc tegra234_timer = {
491 static const struct of_device_id tegra186_timer_of_match[] = {
492 { .compatible = "nvidia,tegra186-timer", .data = &tegra186_timer },
493 { .compatible = "nvidia,tegra234-timer", .data = &tegra234_timer },
496 MODULE_DEVICE_TABLE(of, tegra186_timer_of_match);
498 static struct platform_driver tegra186_wdt_driver = {
500 .name = "tegra186-timer",
501 .pm = &tegra186_timer_pm_ops,
502 .of_match_table = tegra186_timer_of_match,
504 .probe = tegra186_timer_probe,
505 .remove_new = tegra186_timer_remove,
507 module_platform_driver(tegra186_wdt_driver);
509 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
510 MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver");