xref: /linux/drivers/clocksource/timer-tegra186.c (revision 08b7174fb8d126e607e385e34b9e1da4f3be274f)
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/platform_device.h>
12 #include <linux/pm.h>
13 #include <linux/watchdog.h>
14 
15 /* shared registers */
16 #define TKETSC0 0x000
17 #define TKETSC1 0x004
18 #define TKEUSEC 0x008
19 #define TKEOSC  0x00c
20 
21 #define TKEIE(x) (0x100 + ((x) * 4))
22 #define  TKEIE_WDT_MASK(x, y) ((y) << (16 + 4 * (x)))
23 
24 /* timer registers */
25 #define TMRCR 0x000
26 #define  TMRCR_ENABLE BIT(31)
27 #define  TMRCR_PERIODIC BIT(30)
28 #define  TMRCR_PTV(x) ((x) & 0x0fffffff)
29 
30 #define TMRSR 0x004
31 #define  TMRSR_INTR_CLR BIT(30)
32 
33 #define TMRCSSR 0x008
34 #define  TMRCSSR_SRC_USEC (0 << 0)
35 
36 /* watchdog registers */
37 #define WDTCR 0x000
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)
47 
48 #define WDTCMDR 0x008
49 #define  WDTCMDR_DISABLE_COUNTER BIT(1)
50 #define  WDTCMDR_START_COUNTER BIT(0)
51 
52 #define WDTUR 0x00c
53 #define  WDTUR_UNLOCK_PATTERN 0x0000c45a
54 
55 struct tegra186_timer_soc {
56 	unsigned int num_timers;
57 	unsigned int num_wdts;
58 };
59 
60 struct tegra186_tmr {
61 	struct tegra186_timer *parent;
62 	void __iomem *regs;
63 	unsigned int index;
64 	unsigned int hwirq;
65 };
66 
67 struct tegra186_wdt {
68 	struct watchdog_device base;
69 
70 	void __iomem *regs;
71 	unsigned int index;
72 	bool locked;
73 
74 	struct tegra186_tmr *tmr;
75 };
76 
77 static inline struct tegra186_wdt *to_tegra186_wdt(struct watchdog_device *wdd)
78 {
79 	return container_of(wdd, struct tegra186_wdt, base);
80 }
81 
82 struct tegra186_timer {
83 	const struct tegra186_timer_soc *soc;
84 	struct device *dev;
85 	void __iomem *regs;
86 
87 	struct tegra186_wdt *wdt;
88 	struct clocksource usec;
89 	struct clocksource tsc;
90 	struct clocksource osc;
91 };
92 
93 static void tmr_writel(struct tegra186_tmr *tmr, u32 value, unsigned int offset)
94 {
95 	writel_relaxed(value, tmr->regs + offset);
96 }
97 
98 static void wdt_writel(struct tegra186_wdt *wdt, u32 value, unsigned int offset)
99 {
100 	writel_relaxed(value, wdt->regs + offset);
101 }
102 
103 static u32 wdt_readl(struct tegra186_wdt *wdt, unsigned int offset)
104 {
105 	return readl_relaxed(wdt->regs + offset);
106 }
107 
108 static struct tegra186_tmr *tegra186_tmr_create(struct tegra186_timer *tegra,
109 						unsigned int index)
110 {
111 	unsigned int offset = 0x10000 + index * 0x10000;
112 	struct tegra186_tmr *tmr;
113 
114 	tmr = devm_kzalloc(tegra->dev, sizeof(*tmr), GFP_KERNEL);
115 	if (!tmr)
116 		return ERR_PTR(-ENOMEM);
117 
118 	tmr->parent = tegra;
119 	tmr->regs = tegra->regs + offset;
120 	tmr->index = index;
121 	tmr->hwirq = 0;
122 
123 	return tmr;
124 }
125 
126 static const struct watchdog_info tegra186_wdt_info = {
127 	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
128 	.identity = "NVIDIA Tegra186 WDT",
129 };
130 
131 static void tegra186_wdt_disable(struct tegra186_wdt *wdt)
132 {
133 	/* unlock and disable the watchdog */
134 	wdt_writel(wdt, WDTUR_UNLOCK_PATTERN, WDTUR);
135 	wdt_writel(wdt, WDTCMDR_DISABLE_COUNTER, WDTCMDR);
136 
137 	/* disable timer */
138 	tmr_writel(wdt->tmr, 0, TMRCR);
139 }
140 
141 static void tegra186_wdt_enable(struct tegra186_wdt *wdt)
142 {
143 	struct tegra186_timer *tegra = wdt->tmr->parent;
144 	u32 value;
145 
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));
149 
150 	/* clear interrupt */
151 	tmr_writel(wdt->tmr, TMRSR_INTR_CLR, TMRSR);
152 
153 	/* select microsecond source */
154 	tmr_writel(wdt->tmr, TMRCSSR_SRC_USEC, TMRCSSR);
155 
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);
160 
161 	if (!wdt->locked) {
162 		value = wdt_readl(wdt, WDTCR);
163 
164 		/* select the proper timer source */
165 		value &= ~WDTCR_TIMER_SOURCE_MASK;
166 		value |= WDTCR_TIMER_SOURCE(wdt->tmr->index);
167 
168 		/* single timer period since that's already configured */
169 		value &= ~WDTCR_PERIOD_MASK;
170 		value |= WDTCR_PERIOD(1);
171 
172 		/* enable local interrupt for WDT petting */
173 		value |= WDTCR_LOCAL_INT_ENABLE;
174 
175 		/* enable local FIQ and remote interrupt for debug dump */
176 		if (0)
177 			value |= WDTCR_REMOTE_INT_ENABLE |
178 				 WDTCR_LOCAL_FIQ_ENABLE;
179 
180 		/* enable system debug reset (doesn't properly reboot) */
181 		if (0)
182 			value |= WDTCR_SYSTEM_DEBUG_RESET_ENABLE;
183 
184 		/* enable system POR reset */
185 		value |= WDTCR_SYSTEM_POR_RESET_ENABLE;
186 
187 		wdt_writel(wdt, value, WDTCR);
188 	}
189 
190 	wdt_writel(wdt, WDTCMDR_START_COUNTER, WDTCMDR);
191 }
192 
193 static int tegra186_wdt_start(struct watchdog_device *wdd)
194 {
195 	struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
196 
197 	tegra186_wdt_enable(wdt);
198 
199 	return 0;
200 }
201 
202 static int tegra186_wdt_stop(struct watchdog_device *wdd)
203 {
204 	struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
205 
206 	tegra186_wdt_disable(wdt);
207 
208 	return 0;
209 }
210 
211 static int tegra186_wdt_ping(struct watchdog_device *wdd)
212 {
213 	struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
214 
215 	tegra186_wdt_disable(wdt);
216 	tegra186_wdt_enable(wdt);
217 
218 	return 0;
219 }
220 
221 static int tegra186_wdt_set_timeout(struct watchdog_device *wdd,
222 				    unsigned int timeout)
223 {
224 	struct tegra186_wdt *wdt = to_tegra186_wdt(wdd);
225 
226 	if (watchdog_active(&wdt->base))
227 		tegra186_wdt_disable(wdt);
228 
229 	wdt->base.timeout = timeout;
230 
231 	if (watchdog_active(&wdt->base))
232 		tegra186_wdt_enable(wdt);
233 
234 	return 0;
235 }
236 
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,
243 };
244 
245 static struct tegra186_wdt *tegra186_wdt_create(struct tegra186_timer *tegra,
246 						unsigned int index)
247 {
248 	unsigned int offset = 0x10000, source;
249 	struct tegra186_wdt *wdt;
250 	u32 value;
251 	int err;
252 
253 	offset += tegra->soc->num_timers * 0x10000 + index * 0x10000;
254 
255 	wdt = devm_kzalloc(tegra->dev, sizeof(*wdt), GFP_KERNEL);
256 	if (!wdt)
257 		return ERR_PTR(-ENOMEM);
258 
259 	wdt->regs = tegra->regs + offset;
260 	wdt->index = index;
261 
262 	/* read the watchdog configuration since it might be locked down */
263 	value = wdt_readl(wdt, WDTCR);
264 
265 	if (value & WDTCR_LOCAL_INT_ENABLE)
266 		wdt->locked = true;
267 
268 	source = value & WDTCR_TIMER_SOURCE_MASK;
269 
270 	wdt->tmr = tegra186_tmr_create(tegra, source);
271 	if (IS_ERR(wdt->tmr))
272 		return ERR_CAST(wdt->tmr);
273 
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;
279 
280 	err = watchdog_init_timeout(&wdt->base, 5, tegra->dev);
281 	if (err < 0) {
282 		dev_err(tegra->dev, "failed to initialize timeout: %d\n", err);
283 		return ERR_PTR(err);
284 	}
285 
286 	err = devm_watchdog_register_device(tegra->dev, &wdt->base);
287 	if (err < 0) {
288 		dev_err(tegra->dev, "failed to register WDT: %d\n", err);
289 		return ERR_PTR(err);
290 	}
291 
292 	return wdt;
293 }
294 
295 static u64 tegra186_timer_tsc_read(struct clocksource *cs)
296 {
297 	struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
298 						    tsc);
299 	u32 hi, lo, ss;
300 
301 	hi = readl_relaxed(tegra->regs + TKETSC1);
302 
303 	/*
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.
307 	 */
308 	do {
309 		/* snapshot the high 24 bits */
310 		ss = hi;
311 
312 		lo = readl_relaxed(tegra->regs + TKETSC0);
313 		hi = readl_relaxed(tegra->regs + TKETSC1);
314 	} while (hi != ss);
315 
316 	return (u64)hi << 32 | lo;
317 }
318 
319 static int tegra186_timer_tsc_init(struct tegra186_timer *tegra)
320 {
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;
326 
327 	return clocksource_register_hz(&tegra->tsc, 31250000);
328 }
329 
330 static u64 tegra186_timer_osc_read(struct clocksource *cs)
331 {
332 	struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
333 						    osc);
334 
335 	return readl_relaxed(tegra->regs + TKEOSC);
336 }
337 
338 static int tegra186_timer_osc_init(struct tegra186_timer *tegra)
339 {
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;
345 
346 	return clocksource_register_hz(&tegra->osc, 38400000);
347 }
348 
349 static u64 tegra186_timer_usec_read(struct clocksource *cs)
350 {
351 	struct tegra186_timer *tegra = container_of(cs, struct tegra186_timer,
352 						    usec);
353 
354 	return readl_relaxed(tegra->regs + TKEUSEC);
355 }
356 
357 static int tegra186_timer_usec_init(struct tegra186_timer *tegra)
358 {
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;
364 
365 	return clocksource_register_hz(&tegra->usec, USEC_PER_SEC);
366 }
367 
368 static irqreturn_t tegra186_timer_irq(int irq, void *data)
369 {
370 	struct tegra186_timer *tegra = data;
371 
372 	if (watchdog_active(&tegra->wdt->base)) {
373 		tegra186_wdt_disable(tegra->wdt);
374 		tegra186_wdt_enable(tegra->wdt);
375 	}
376 
377 	return IRQ_HANDLED;
378 }
379 
380 static int tegra186_timer_probe(struct platform_device *pdev)
381 {
382 	struct device *dev = &pdev->dev;
383 	struct tegra186_timer *tegra;
384 	unsigned int irq;
385 	int err;
386 
387 	tegra = devm_kzalloc(dev, sizeof(*tegra), GFP_KERNEL);
388 	if (!tegra)
389 		return -ENOMEM;
390 
391 	tegra->soc = of_device_get_match_data(dev);
392 	dev_set_drvdata(dev, tegra);
393 	tegra->dev = dev;
394 
395 	tegra->regs = devm_platform_ioremap_resource(pdev, 0);
396 	if (IS_ERR(tegra->regs))
397 		return PTR_ERR(tegra->regs);
398 
399 	err = platform_get_irq(pdev, 0);
400 	if (err < 0)
401 		return err;
402 
403 	irq = err;
404 
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);
410 		return err;
411 	}
412 
413 	err = tegra186_timer_tsc_init(tegra);
414 	if (err < 0) {
415 		dev_err(dev, "failed to register TSC counter: %d\n", err);
416 		return err;
417 	}
418 
419 	err = tegra186_timer_osc_init(tegra);
420 	if (err < 0) {
421 		dev_err(dev, "failed to register OSC counter: %d\n", err);
422 		goto unregister_tsc;
423 	}
424 
425 	err = tegra186_timer_usec_init(tegra);
426 	if (err < 0) {
427 		dev_err(dev, "failed to register USEC counter: %d\n", err);
428 		goto unregister_osc;
429 	}
430 
431 	err = devm_request_irq(dev, irq, tegra186_timer_irq, 0,
432 			       "tegra186-timer", tegra);
433 	if (err < 0) {
434 		dev_err(dev, "failed to request IRQ#%u: %d\n", irq, err);
435 		goto unregister_usec;
436 	}
437 
438 	return 0;
439 
440 unregister_usec:
441 	clocksource_unregister(&tegra->usec);
442 unregister_osc:
443 	clocksource_unregister(&tegra->osc);
444 unregister_tsc:
445 	clocksource_unregister(&tegra->tsc);
446 	return err;
447 }
448 
449 static void tegra186_timer_remove(struct platform_device *pdev)
450 {
451 	struct tegra186_timer *tegra = platform_get_drvdata(pdev);
452 
453 	clocksource_unregister(&tegra->usec);
454 	clocksource_unregister(&tegra->osc);
455 	clocksource_unregister(&tegra->tsc);
456 }
457 
458 static int __maybe_unused tegra186_timer_suspend(struct device *dev)
459 {
460 	struct tegra186_timer *tegra = dev_get_drvdata(dev);
461 
462 	if (watchdog_active(&tegra->wdt->base))
463 		tegra186_wdt_disable(tegra->wdt);
464 
465 	return 0;
466 }
467 
468 static int __maybe_unused tegra186_timer_resume(struct device *dev)
469 {
470 	struct tegra186_timer *tegra = dev_get_drvdata(dev);
471 
472 	if (watchdog_active(&tegra->wdt->base))
473 		tegra186_wdt_enable(tegra->wdt);
474 
475 	return 0;
476 }
477 
478 static SIMPLE_DEV_PM_OPS(tegra186_timer_pm_ops, tegra186_timer_suspend,
479 			 tegra186_timer_resume);
480 
481 static const struct tegra186_timer_soc tegra186_timer = {
482 	.num_timers = 10,
483 	.num_wdts = 3,
484 };
485 
486 static const struct tegra186_timer_soc tegra234_timer = {
487 	.num_timers = 16,
488 	.num_wdts = 3,
489 };
490 
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 },
494 	{ }
495 };
496 MODULE_DEVICE_TABLE(of, tegra186_timer_of_match);
497 
498 static struct platform_driver tegra186_wdt_driver = {
499 	.driver = {
500 		.name = "tegra186-timer",
501 		.pm = &tegra186_timer_pm_ops,
502 		.of_match_table = tegra186_timer_of_match,
503 	},
504 	.probe = tegra186_timer_probe,
505 	.remove_new = tegra186_timer_remove,
506 };
507 module_platform_driver(tegra186_wdt_driver);
508 
509 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
510 MODULE_DESCRIPTION("NVIDIA Tegra186 timers driver");
511