Lines Matching +full:wdt +full:- +full:timer +full:- +full:index
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2019-2020 NVIDIA Corporation. All rights reserved.
24 /* timer registers */
63 unsigned int index; member
71 unsigned int index; member
87 struct tegra186_wdt *wdt; member
95 writel_relaxed(value, tmr->regs + offset); in tmr_writel()
98 static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset) in wdt_writel() argument
100 writel_relaxed(value, wdt->regs + offset); in wdt_writel()
103 static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset) in wdt_readl() argument
105 return readl_relaxed(wdt->regs + offset); in wdt_readl()
109 unsigned int index) in tegra186_tmr_create() argument
111 unsigned int offset = 0x10000 + index * 0x10000; in tegra186_tmr_create()
114 tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL); in tegra186_tmr_create()
116 return ERR_PTR(-ENOMEM); in tegra186_tmr_create()
118 tmr->parent = tegra; in tegra186_tmr_create()
119 tmr->regs = tegra->regs + offset; in tegra186_tmr_create()
120 tmr->index = index; in tegra186_tmr_create()
121 tmr->hwirq = 0; in tegra186_tmr_create()
128 .identity = "NVIDIA Tegra186 WDT",
131 static void tegra186_wdt_disable(struct tegra186_wdt *wdt) in tegra186_wdt_disable() argument
134 wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR); in tegra186_wdt_disable()
135 wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR); in tegra186_wdt_disable()
137 /* disable timer */ in tegra186_wdt_disable()
138 tmr_writel(wdt->tmr, 0, TMRCR); in tegra186_wdt_disable()
141 static void tegra186_wdt_enable(struct tegra186_wdt *wdt) in tegra186_wdt_enable() argument
143 struct tegra186_timer *tegra = wdt->tmr->parent; in tegra186_wdt_enable()
147 value = TKEIE_WDT_MASK(wdt->index, 1); in tegra186_wdt_enable()
148 writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq)); in tegra186_wdt_enable()
151 tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR); in tegra186_wdt_enable()
154 tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR); in tegra186_wdt_enable()
156 /* configure timer (system reset happens on the fifth expiration) */ in tegra186_wdt_enable()
157 value = TMRCR_PTV(wdt->base.timeout * USEC_PER_SEC / 5) | in tegra186_wdt_enable()
159 tmr_writel(wdt->tmr, value, TMRCR); in tegra186_wdt_enable()
161 if (!wdt->locked) { in tegra186_wdt_enable()
162 value = wdt_readl(wdt, WDTCR); in tegra186_wdt_enable()
164 /* select the proper timer source */ in tegra186_wdt_enable()
166 value |= WDTCR_TIMER_SOURCE(wdt->tmr->index); in tegra186_wdt_enable()
168 /* single timer period since that's already configured */ in tegra186_wdt_enable()
172 /* enable local interrupt for WDT petting */ in tegra186_wdt_enable()
187 wdt_writel(wdt, value, WDTCR); in tegra186_wdt_enable()
190 wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR); in tegra186_wdt_enable()
195 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd); in tegra186_wdt_start() local
197 tegra186_wdt_enable(wdt); in tegra186_wdt_start()
204 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd); in tegra186_wdt_stop() local
206 tegra186_wdt_disable(wdt); in tegra186_wdt_stop()
213 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd); in tegra186_wdt_ping() local
215 tegra186_wdt_disable(wdt); in tegra186_wdt_ping()
216 tegra186_wdt_enable(wdt); in tegra186_wdt_ping()
224 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd); in tegra186_wdt_set_timeout() local
226 if (watchdog_active(&wdt->base)) in tegra186_wdt_set_timeout()
227 tegra186_wdt_disable(wdt); in tegra186_wdt_set_timeout()
229 wdt->base.timeout = timeout; in tegra186_wdt_set_timeout()
231 if (watchdog_active(&wdt->base)) in tegra186_wdt_set_timeout()
232 tegra186_wdt_enable(wdt); in tegra186_wdt_set_timeout()
246 unsigned int index) in tegra186_wdt_create() argument
249 struct tegra186_wdt *wdt; in tegra186_wdt_create() local
253 offset += tegra->soc->num_timers * 0x10000 + index * 0x10000; in tegra186_wdt_create()
255 wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL); in tegra186_wdt_create()
256 if (!wdt) in tegra186_wdt_create()
257 return ERR_PTR(-ENOMEM); in tegra186_wdt_create()
259 wdt->regs = tegra->regs + offset; in tegra186_wdt_create()
260 wdt->index = index; in tegra186_wdt_create()
263 value = wdt_readl(wdt, WDTCR); in tegra186_wdt_create()
266 wdt->locked = true; in tegra186_wdt_create()
270 wdt->tmr = tegra186_tmr_create(tegra, source); in tegra186_wdt_create()
271 if (IS_ERR(wdt->tmr)) in tegra186_wdt_create()
272 return ERR_CAST(wdt->tmr); in tegra186_wdt_create()
274 wdt->base.info = &tegra186_wdt_info; in tegra186_wdt_create()
275 wdt->base.ops = &tegra186_wdt_ops; in tegra186_wdt_create()
276 wdt->base.min_timeout = 1; in tegra186_wdt_create()
277 wdt->base.max_timeout = 255; in tegra186_wdt_create()
278 wdt->base.parent = tegra->dev; in tegra186_wdt_create()
280 err = watchdog_init_timeout(&wdt->base, 5, tegra->dev); in tegra186_wdt_create()
282 dev_err(tegra->dev, "failed to initialize timeout: %d\n", err); in tegra186_wdt_create()
286 err = devm_watchdog_register_device(tegra->dev, &wdt->base); in tegra186_wdt_create()
288 dev_err(tegra->dev, "failed to register WDT: %d\n", err); in tegra186_wdt_create()
292 return wdt; in tegra186_wdt_create()
301 hi = readl_relaxed(tegra->regs + TKETSC1); in tegra186_timer_tsc_read()
304 * The 56-bit value of the TSC is spread across two registers that are in tegra186_timer_tsc_read()
312 lo = readl_relaxed(tegra->regs + TKETSC0); in tegra186_timer_tsc_read()
313 hi = readl_relaxed(tegra->regs + TKETSC1); in tegra186_timer_tsc_read()
321 tegra->tsc.name = "tsc"; in tegra186_timer_tsc_init()
322 tegra->tsc.rating = 300; in tegra186_timer_tsc_init()
323 tegra->tsc.read = tegra186_timer_tsc_read; in tegra186_timer_tsc_init()
324 tegra->tsc.mask = CLOCKSOURCE_MASK(56); in tegra186_timer_tsc_init()
325 tegra->tsc.flags = CLOCK_SOURCE_IS_CONTINUOUS; in tegra186_timer_tsc_init()
327 return clocksource_register_hz(&tegra->tsc, 31250000); in tegra186_timer_tsc_init()
335 return readl_relaxed(tegra->regs + TKEOSC); in tegra186_timer_osc_read()
340 tegra->osc.name = "osc"; in tegra186_timer_osc_init()
341 tegra->osc.rating = 300; in tegra186_timer_osc_init()
342 tegra->osc.read = tegra186_timer_osc_read; in tegra186_timer_osc_init()
343 tegra->osc.mask = CLOCKSOURCE_MASK(32); in tegra186_timer_osc_init()
344 tegra->osc.flags = CLOCK_SOURCE_IS_CONTINUOUS; in tegra186_timer_osc_init()
346 return clocksource_register_hz(&tegra->osc, 38400000); in tegra186_timer_osc_init()
354 return readl_relaxed(tegra->regs + TKEUSEC); in tegra186_timer_usec_read()
359 tegra->usec.name = "usec"; in tegra186_timer_usec_init()
360 tegra->usec.rating = 300; in tegra186_timer_usec_init()
361 tegra->usec.read = tegra186_timer_usec_read; in tegra186_timer_usec_init()
362 tegra->usec.mask = CLOCKSOURCE_MASK(32); in tegra186_timer_usec_init()
363 tegra->usec.flags = CLOCK_SOURCE_IS_CONTINUOUS; in tegra186_timer_usec_init()
365 return clocksource_register_hz(&tegra->usec, USEC_PER_SEC); in tegra186_timer_usec_init()
372 if (watchdog_active(&tegra->wdt->base)) { in tegra186_timer_irq()
373 tegra186_wdt_disable(tegra->wdt); in tegra186_timer_irq()
374 tegra186_wdt_enable(tegra->wdt); in tegra186_timer_irq()
382 struct device *dev = &pdev->dev; in tegra186_timer_probe()
389 return -ENOMEM; in tegra186_timer_probe()
391 tegra->soc = of_device_get_match_data(dev); in tegra186_timer_probe()
393 tegra->dev = dev; in tegra186_timer_probe()
395 tegra->regs = devm_platform_ioremap_resource(pdev, 0); in tegra186_timer_probe()
396 if (IS_ERR(tegra->regs)) in tegra186_timer_probe()
397 return PTR_ERR(tegra->regs); in tegra186_timer_probe()
405 /* create a watchdog using a preconfigured timer */ in tegra186_timer_probe()
406 tegra->wdt = tegra186_wdt_create(tegra, 0); in tegra186_timer_probe()
407 if (IS_ERR(tegra->wdt)) { in tegra186_timer_probe()
408 err = PTR_ERR(tegra->wdt); in tegra186_timer_probe()
409 dev_err(dev, "failed to create WDT: %d\n", err); in tegra186_timer_probe()
432 "tegra186-timer", tegra); in tegra186_timer_probe()
441 clocksource_unregister(&tegra->usec); in tegra186_timer_probe()
443 clocksource_unregister(&tegra->osc); in tegra186_timer_probe()
445 clocksource_unregister(&tegra->tsc); in tegra186_timer_probe()
453 clocksource_unregister(&tegra->usec); in tegra186_timer_remove()
454 clocksource_unregister(&tegra->osc); in tegra186_timer_remove()
455 clocksource_unregister(&tegra->tsc); in tegra186_timer_remove()
462 if (watchdog_active(&tegra->wdt->base)) in tegra186_timer_suspend()
463 tegra186_wdt_disable(tegra->wdt); in tegra186_timer_suspend()
472 if (watchdog_active(&tegra->wdt->base)) in tegra186_timer_resume()
473 tegra186_wdt_enable(tegra->wdt); in tegra186_timer_resume()
492 { .compatible = "nvidia,tegra186-timer", .data = &tegra186_timer },
493 { .compatible = "nvidia,tegra234-timer", .data = &tegra234_timer },
500 .name = "tegra186-timer",