Merge tag 'trace-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux...
[linux-2.6-block.git] / drivers / clocksource / timer-tegra186.c
CommitLineData
42cee19a
TR
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2019-2020 NVIDIA Corporation. All rights reserved.
4 */
5
6#include <linux/clocksource.h>
7#include <linux/module.h>
8#include <linux/interrupt.h>
9#include <linux/io.h>
10#include <linux/of.h>
11#include <linux/of_device.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
34#define TMRCSSR 0x008
35#define TMRCSSR_SRC_USEC (0 << 0)
36
37/* watchdog registers */
38#define WDTCR 0x000
39#define WDTCR_SYSTEM_POR_RESET_ENABLE BIT(16)
40#define WDTCR_SYSTEM_DEBUG_RESET_ENABLE BIT(15)
41#define WDTCR_REMOTE_INT_ENABLE BIT(14)
42#define WDTCR_LOCAL_FIQ_ENABLE BIT(13)
43#define WDTCR_LOCAL_INT_ENABLE BIT(12)
44#define WDTCR_PERIOD_MASK (0xff << 4)
45#define WDTCR_PERIOD(x) (((x) & 0xff) << 4)
46#define WDTCR_TIMER_SOURCE_MASK 0xf
47#define WDTCR_TIMER_SOURCE(x) ((x) & 0xf)
48
49#define WDTCMDR 0x008
50#define WDTCMDR_DISABLE_COUNTER BIT(1)
51#define WDTCMDR_START_COUNTER BIT(0)
52
53#define WDTUR 0x00c
54#define WDTUR_UNLOCK_PATTERN 0x0000c45a
55
56struct tegra186_timer_soc {
57 unsigned int num_timers;
58 unsigned int num_wdts;
59};
60
61struct tegra186_tmr {
62 struct tegra186_timer *parent;
63 void __iomem *regs;
64 unsigned int index;
65 unsigned int hwirq;
66};
67
68struct tegra186_wdt {
69 struct watchdog_device base;
70
71 void __iomem *regs;
72 unsigned int index;
73 bool locked;
74
75 struct tegra186_tmr *tmr;
76};
77
78static inline struct tegra186_wdt *to_tegra186_wdt(struct watchdog_device *wdd)
79{
80 return container_of(wdd, struct tegra186_wdt, base);
81}
82
83struct tegra186_timer {
84 const struct tegra186_timer_soc *soc;
85 struct device *dev;
86 void __iomem *regs;
87
88 struct tegra186_wdt *wdt;
89 struct clocksource usec;
90 struct clocksource tsc;
91 struct clocksource osc;
92};
93
94static void tmr_writel(struct tegra186_tmr *tmr, u32 value, unsigned int offset)
95{
96 writel_relaxed(value, tmr->regs + offset);
97}
98
99static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset)
100{
101 writel_relaxed(value, wdt->regs + offset);
102}
103
104static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset)
105{
106 return readl_relaxed(wdt->regs + offset);
107}
108
109static struct tegra186_tmr *tegra186_tmr_create(struct tegra186_timer *tegra,
110 unsigned int index)
111{
112 unsigned int offset = 0x10000 + index * 0x10000;
113 struct tegra186_tmr *tmr;
114
115 tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL);
116 if (!tmr)
117 return ERR_PTR(-ENOMEM);
118
119 tmr->parent = tegra;
120 tmr->regs = tegra->regs + offset;
121 tmr->index = index;
122 tmr->hwirq = 0;
123
124 return tmr;
125}
126
127static const struct watchdog_info tegra186_wdt_info = {
128 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
129 .identity = "NVIDIA Tegra186 WDT",
130};
131
132static void tegra186_wdt_disable(struct tegra186_wdt *wdt)
133{
134 /* unlock and disable the watchdog */
135 wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
136 wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
137
138 /* disable timer */
139 tmr_writel(wdt->tmr, 0, TMRCR);
140}
141
142static void tegra186_wdt_enable(struct tegra186_wdt *wdt)
143{
144 struct tegra186_timer *tegra = wdt->tmr->parent;
145 u32 value;
146
147 /* unmask hardware IRQ, this may have been lost across powergate */
148 value = TKEIE_WDT_MASK(wdt->index, 1);
149 writel(value, tegra->regs + TKEIE(wdt->tmr->hwirq));
150
151 /* clear interrupt */
152 tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
153
154 /* select microsecond source */
155 tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
156
157 /* configure timer (system reset happens on the fifth expiration) */
158 value = TMRCR_PTV(wdt->base.timeout * USEC_PER_SEC / 5) |
159 TMRCR_PERIODIC | TMRCR_ENABLE;
160 tmr_writel(wdt->tmr, value, TMRCR);
161
162 if (!wdt->locked) {
163 value = wdt_readl(wdt, WDTCR);
164
165 /* select the proper timer source */
166 value &= ~WDTCR_TIMER_SOURCE_MASK;
167 value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
168
169 /* single timer period since that's already configured */
170 value &= ~WDTCR_PERIOD_MASK;
171 value |= WDTCR_PERIOD(1);
172
173 /* enable local interrupt for WDT petting */
174 value |= WDTCR_LOCAL_INT_ENABLE;
175
176 /* enable local FIQ and remote interrupt for debug dump */
177 if (0)
178 value |= WDTCR_REMOTE_INT_ENABLE |
179 WDTCR_LOCAL_FIQ_ENABLE;
180
181 /* enable system debug reset (doesn't properly reboot) */
182 if (0)
183 value |= WDTCR_SYSTEM_DEBUG_RESET_ENABLE;
184
185 /* enable system POR reset */
186 value |= WDTCR_SYSTEM_POR_RESET_ENABLE;
187
188 wdt_writel(wdt, value, WDTCR);
189 }
190
191 wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR);
192}
193
194static int tegra186_wdt_start(struct watchdog_device *wdd)
195{
196 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
197
198 tegra186_wdt_enable(wdt);
199
200 return 0;
201}
202
203static int tegra186_wdt_stop(struct watchdog_device *wdd)
204{
205 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
206
207 tegra186_wdt_disable(wdt);
208
209 return 0;
210}
211
212static int tegra186_wdt_ping(struct watchdog_device *wdd)
213{
214 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
215
216 tegra186_wdt_disable(wdt);
217 tegra186_wdt_enable(wdt);
218
219 return 0;
220}
221
222static int tegra186_wdt_set_timeout(struct watchdog_device *wdd,
223 unsigned int timeout)
224{
225 struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
226
227 if (watchdog_active(&wdt->base))
228 tegra186_wdt_disable(wdt);
229
230 wdt->base.timeout = timeout;
231
232 if (watchdog_active(&wdt->base))
233 tegra186_wdt_enable(wdt);
234
235 return 0;
236}
237
238static const struct watchdog_ops tegra186_wdt_ops = {
239 .owner = THIS_MODULE,
240 .start = tegra186_wdt_start,
241 .stop = tegra186_wdt_stop,
242 .ping = tegra186_wdt_ping,
243 .set_timeout = tegra186_wdt_set_timeout,
244};
245
246static struct tegra186_wdt *tegra186_wdt_create(struct tegra186_timer *tegra,
247 unsigned int index)
248{
249 unsigned int offset = 0x10000, source;
250 struct tegra186_wdt *wdt;
251 u32 value;
252 int err;
253
254 offset += tegra->soc->num_timers * 0x10000 + index * 0x10000;
255
256 wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL);
257 if (!wdt)
258 return ERR_PTR(-ENOMEM);
259
260 wdt->regs = tegra->regs + offset;
261 wdt->index = index;
262
263 /* read the watchdog configuration since it might be locked down */
264 value = wdt_readl(wdt, WDTCR);
265
266 if (value & WDTCR_LOCAL_INT_ENABLE)
267 wdt->locked = true;
268
269 source = value & WDTCR_TIMER_SOURCE_MASK;
270
271 wdt->tmr = tegra186_tmr_create(tegra, source);
272 if (IS_ERR(wdt->tmr))
273 return ERR_CAST(wdt->tmr);
274
275 wdt->base.info = &tegra186_wdt_info;
276 wdt->base.ops = &tegra186_wdt_ops;
277 wdt->base.min_timeout = 1;
278 wdt->base.max_timeout = 255;
279 wdt->base.parent = tegra->dev;
280
281 err = watchdog_init_timeout(&wdt->base, 5, tegra->dev);
282 if (err < 0) {
283 dev_err(tegra->dev, "failed to initialize timeout: %d\n", err);
284 return ERR_PTR(err);
285 }
286
287 err = devm_watchdog_register_device(tegra->dev, &wdt->base);
288 if (err < 0) {
289 dev_err(tegra->dev, "failed to register WDT: %d\n", err);
290 return ERR_PTR(err);
291 }
292
293 return wdt;
294}
295
296static u64 tegra186_timer_tsc_read(struct clocksource *cs)
297{
298 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
299 tsc);
300 u32 hi, lo, ss;
301
302 hi = readl_relaxed(tegra->regs + TKETSC1);
303
304 /*
305 * The 56-bit value of the TSC is spread across two registers that are
306 * not synchronized. In order to read them atomically, ensure that the
307 * high 24 bits match before and after reading the low 32 bits.
308 */
309 do {
310 /* snapshot the high 24 bits */
311 ss = hi;
312
313 lo = readl_relaxed(tegra->regs + TKETSC0);
314 hi = readl_relaxed(tegra->regs + TKETSC1);
315 } while (hi != ss);
316
317 return (u64)hi << 32 | lo;
318}
319
320static int tegra186_timer_tsc_init(struct tegra186_timer *tegra)
321{
322 tegra->tsc.name = "tsc";
323 tegra->tsc.rating = 300;
324 tegra->tsc.read = tegra186_timer_tsc_read;
325 tegra->tsc.mask = CLOCKSOURCE_MASK(56);
326 tegra->tsc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
327
328 return clocksource_register_hz(&tegra->tsc, 31250000);
329}
330
331static u64 tegra186_timer_osc_read(struct clocksource *cs)
332{
333 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
334 osc);
335
336 return readl_relaxed(tegra->regs + TKEOSC);
337}
338
339static int tegra186_timer_osc_init(struct tegra186_timer *tegra)
340{
341 tegra->osc.name = "osc";
342 tegra->osc.rating = 300;
343 tegra->osc.read = tegra186_timer_osc_read;
344 tegra->osc.mask = CLOCKSOURCE_MASK(32);
345 tegra->osc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
346
347 return clocksource_register_hz(&tegra->osc, 38400000);
348}
349
350static u64 tegra186_timer_usec_read(struct clocksource *cs)
351{
352 struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
353 usec);
354
355 return readl_relaxed(tegra->regs + TKEUSEC);
356}
357
358static int tegra186_timer_usec_init(struct tegra186_timer *tegra)
359{
360 tegra->usec.name = "usec";
361 tegra->usec.rating = 300;
362 tegra->usec.read = tegra186_timer_usec_read;
363 tegra->usec.mask = CLOCKSOURCE_MASK(32);
364 tegra->usec.flags = CLOCK_SOURCE_IS_CONTINUOUS;
365
366 return clocksource_register_hz(&tegra->usec, USEC_PER_SEC);
367}
368
369static irqreturn_t tegra186_timer_irq(int irq, void *data)
370{
371 struct tegra186_timer *tegra = data;
372
373 if (watchdog_active(&tegra->wdt->base)) {
374 tegra186_wdt_disable(tegra->wdt);
375 tegra186_wdt_enable(tegra->wdt);
376 }
377
378 return IRQ_HANDLED;
379}
380
381static int tegra186_timer_probe(struct platform_device *pdev)
382{
383 struct device *dev = &pdev->dev;
384 struct tegra186_timer *tegra;
385 unsigned int irq;
386 int err;
387
388 tegra = devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL);
389 if (!tegra)
390 return -ENOMEM;
391
392 tegra->soc = of_device_get_match_data(dev);
393 dev_set_drvdata(dev, tegra);
394 tegra->dev = dev;
395
396 tegra->regs = devm_platform_ioremap_resource(pdev, 0);
397 if (IS_ERR(tegra->regs))
398 return PTR_ERR(tegra->regs);
399
400 err = platform_get_irq(pdev, 0);
401 if (err < 0)
402 return err;
403
404 irq = err;
405
406 /* create a watchdog using a preconfigured timer */
407 tegra->wdt = tegra186_wdt_create(tegra, 0);
408 if (IS_ERR(tegra->wdt)) {
409 err = PTR_ERR(tegra->wdt);
410 dev_err(dev, "failed to create WDT: %d\n", err);
411 return err;
412 }
413
414 err = tegra186_timer_tsc_init(tegra);
415 if (err < 0) {
416 dev_err(dev, "failed to register TSC counter: %d\n", err);
417 return err;
418 }
419
420 err = tegra186_timer_osc_init(tegra);
421 if (err < 0) {
422 dev_err(dev, "failed to register OSC counter: %d\n", err);
423 goto unregister_tsc;
424 }
425
426 err = tegra186_timer_usec_init(tegra);
427 if (err < 0) {
428 dev_err(dev, "failed to register USEC counter: %d\n", err);
429 goto unregister_osc;
430 }
431
432 err = devm_request_irq(dev, irq, tegra186_timer_irq, 0,
433 "tegra186-timer", tegra);
434 if (err < 0) {
435 dev_err(dev, "failed to request IRQ#%u: %d\n", irq, err);
436 goto unregister_usec;
437 }
438
439 return 0;
440
441unregister_usec:
442 clocksource_unregister(&tegra->usec);
443unregister_osc:
444 clocksource_unregister(&tegra->osc);
445unregister_tsc:
446 clocksource_unregister(&tegra->tsc);
447 return err;
448}
449
450static int tegra186_timer_remove(struct platform_device *pdev)
451{
452 struct tegra186_timer *tegra = platform_get_drvdata(pdev);
453
454 clocksource_unregister(&tegra->usec);
455 clocksource_unregister(&tegra->osc);
456 clocksource_unregister(&tegra->tsc);
457
458 return 0;
459}
460
461static int __maybe_unused tegra186_timer_suspend(struct device *dev)
462{
463 struct tegra186_timer *tegra = dev_get_drvdata(dev);
464
465 if (watchdog_active(&tegra->wdt->base))
466 tegra186_wdt_disable(tegra->wdt);
467
468 return 0;
469}
470
471static int __maybe_unused tegra186_timer_resume(struct device *dev)
472{
473 struct tegra186_timer *tegra = dev_get_drvdata(dev);
474
475 if (watchdog_active(&tegra->wdt->base))
476 tegra186_wdt_enable(tegra->wdt);
477
478 return 0;
479}
480
481static SIMPLE_DEV_PM_OPS(tegra186_timer_pm_ops, tegra186_timer_suspend,
482 tegra186_timer_resume);
483
484static const struct tegra186_timer_soc tegra186_timer = {
485 .num_timers = 10,
486 .num_wdts = 3,
487};
488
07385a60
K
489static const struct tegra186_timer_soc tegra234_timer = {
490 .num_timers = 16,
491 .num_wdts = 3,
492};
493
42cee19a
TR
494static const struct of_device_id tegra186_timer_of_match[] = {
495 { .compatible = "nvidia,tegra186-timer", .data = &tegra186_timer },
07385a60 496 { .compatible = "nvidia,tegra234-timer", .data = &tegra234_timer },
42cee19a
TR
497 { }
498};
499MODULE_DEVICE_TABLE(of, tegra186_timer_of_match);
500
501static struct platform_driver tegra186_wdt_driver = {
502 .driver = {
503 .name = "tegra186-timer",
504 .pm = &tegra186_timer_pm_ops,
505 .of_match_table = tegra186_timer_of_match,
506 },
507 .probe = tegra186_timer_probe,
508 .remove = tegra186_timer_remove,
509};
510module_platform_driver(tegra186_wdt_driver);
511
512MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
513MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver");