xref: /openbmc/linux/drivers/clocksource/timer-tegra186.c (revision 7f33105cdd59a99d068d3d147723a865d10e2260)
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