162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2010 Google, Inc.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author:
662306a36Sopenharmony_ci *	Colin Cross <ccross@google.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define pr_fmt(fmt)	"tegra-timer: " fmt
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/clk.h>
1262306a36Sopenharmony_ci#include <linux/clockchips.h>
1362306a36Sopenharmony_ci#include <linux/cpu.h>
1462306a36Sopenharmony_ci#include <linux/cpumask.h>
1562306a36Sopenharmony_ci#include <linux/delay.h>
1662306a36Sopenharmony_ci#include <linux/err.h>
1762306a36Sopenharmony_ci#include <linux/interrupt.h>
1862306a36Sopenharmony_ci#include <linux/of_address.h>
1962306a36Sopenharmony_ci#include <linux/of_irq.h>
2062306a36Sopenharmony_ci#include <linux/percpu.h>
2162306a36Sopenharmony_ci#include <linux/sched_clock.h>
2262306a36Sopenharmony_ci#include <linux/time.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "timer-of.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define RTC_SECONDS		0x08
2762306a36Sopenharmony_ci#define RTC_SHADOW_SECONDS	0x0c
2862306a36Sopenharmony_ci#define RTC_MILLISECONDS	0x10
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define TIMERUS_CNTR_1US	0x10
3162306a36Sopenharmony_ci#define TIMERUS_USEC_CFG	0x14
3262306a36Sopenharmony_ci#define TIMERUS_CNTR_FREEZE	0x4c
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define TIMER_PTV		0x0
3562306a36Sopenharmony_ci#define TIMER_PTV_EN		BIT(31)
3662306a36Sopenharmony_ci#define TIMER_PTV_PER		BIT(30)
3762306a36Sopenharmony_ci#define TIMER_PCR		0x4
3862306a36Sopenharmony_ci#define TIMER_PCR_INTR_CLR	BIT(30)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define TIMER1_BASE		0x00
4162306a36Sopenharmony_ci#define TIMER2_BASE		0x08
4262306a36Sopenharmony_ci#define TIMER3_BASE		0x50
4362306a36Sopenharmony_ci#define TIMER4_BASE		0x58
4462306a36Sopenharmony_ci#define TIMER10_BASE		0x90
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define TIMER1_IRQ_IDX		0
4762306a36Sopenharmony_ci#define TIMER10_IRQ_IDX		10
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define TIMER_1MHz		1000000
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic u32 usec_config;
5262306a36Sopenharmony_cistatic void __iomem *timer_reg_base;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic int tegra_timer_set_next_event(unsigned long cycles,
5562306a36Sopenharmony_ci				      struct clock_event_device *evt)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(to_timer_of(evt));
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	/*
6062306a36Sopenharmony_ci	 * Tegra's timer uses n+1 scheme for the counter, i.e. timer will
6162306a36Sopenharmony_ci	 * fire after one tick if 0 is loaded.
6262306a36Sopenharmony_ci	 *
6362306a36Sopenharmony_ci	 * The minimum and maximum numbers of oneshot ticks are defined
6462306a36Sopenharmony_ci	 * by clockevents_config_and_register(1, 0x1fffffff + 1) invocation
6562306a36Sopenharmony_ci	 * below in the code. Hence the cycles (ticks) can't be outside of
6662306a36Sopenharmony_ci	 * a range supportable by hardware.
6762306a36Sopenharmony_ci	 */
6862306a36Sopenharmony_ci	writel_relaxed(TIMER_PTV_EN | (cycles - 1), reg_base + TIMER_PTV);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return 0;
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic int tegra_timer_shutdown(struct clock_event_device *evt)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(to_timer_of(evt));
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	writel_relaxed(0, reg_base + TIMER_PTV);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic int tegra_timer_set_periodic(struct clock_event_device *evt)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(to_timer_of(evt));
8562306a36Sopenharmony_ci	unsigned long period = timer_of_period(to_timer_of(evt));
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	writel_relaxed(TIMER_PTV_EN | TIMER_PTV_PER | (period - 1),
8862306a36Sopenharmony_ci		       reg_base + TIMER_PTV);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	return 0;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic irqreturn_t tegra_timer_isr(int irq, void *dev_id)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct clock_event_device *evt = dev_id;
9662306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(to_timer_of(evt));
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	writel_relaxed(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR);
9962306a36Sopenharmony_ci	evt->event_handler(evt);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return IRQ_HANDLED;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic void tegra_timer_suspend(struct clock_event_device *evt)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(to_timer_of(evt));
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	writel_relaxed(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic void tegra_timer_resume(struct clock_event_device *evt)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	writel_relaxed(usec_config, timer_reg_base + TIMERUS_USEC_CFG);
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct timer_of, tegra_to) = {
11762306a36Sopenharmony_ci	.flags = TIMER_OF_CLOCK | TIMER_OF_BASE,
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	.clkevt = {
12062306a36Sopenharmony_ci		.name = "tegra_timer",
12162306a36Sopenharmony_ci		.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
12262306a36Sopenharmony_ci		.set_next_event = tegra_timer_set_next_event,
12362306a36Sopenharmony_ci		.set_state_shutdown = tegra_timer_shutdown,
12462306a36Sopenharmony_ci		.set_state_periodic = tegra_timer_set_periodic,
12562306a36Sopenharmony_ci		.set_state_oneshot = tegra_timer_shutdown,
12662306a36Sopenharmony_ci		.tick_resume = tegra_timer_shutdown,
12762306a36Sopenharmony_ci		.suspend = tegra_timer_suspend,
12862306a36Sopenharmony_ci		.resume = tegra_timer_resume,
12962306a36Sopenharmony_ci	},
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic int tegra_timer_setup(unsigned int cpu)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct timer_of *to = per_cpu_ptr(&tegra_to, cpu);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	writel_relaxed(0, timer_of_base(to) + TIMER_PTV);
13762306a36Sopenharmony_ci	writel_relaxed(TIMER_PCR_INTR_CLR, timer_of_base(to) + TIMER_PCR);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	irq_force_affinity(to->clkevt.irq, cpumask_of(cpu));
14062306a36Sopenharmony_ci	enable_irq(to->clkevt.irq);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/*
14362306a36Sopenharmony_ci	 * Tegra's timer uses n+1 scheme for the counter, i.e. timer will
14462306a36Sopenharmony_ci	 * fire after one tick if 0 is loaded and thus minimum number of
14562306a36Sopenharmony_ci	 * ticks is 1. In result both of the clocksource's tick limits are
14662306a36Sopenharmony_ci	 * higher than a minimum and maximum that hardware register can
14762306a36Sopenharmony_ci	 * take by 1, this is then taken into account by set_next_event
14862306a36Sopenharmony_ci	 * callback.
14962306a36Sopenharmony_ci	 */
15062306a36Sopenharmony_ci	clockevents_config_and_register(&to->clkevt, timer_of_rate(to),
15162306a36Sopenharmony_ci					1, /* min */
15262306a36Sopenharmony_ci					0x1fffffff + 1); /* max 29 bits + 1 */
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return 0;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic int tegra_timer_stop(unsigned int cpu)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	struct timer_of *to = per_cpu_ptr(&tegra_to, cpu);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	to->clkevt.set_state_shutdown(&to->clkevt);
16262306a36Sopenharmony_ci	disable_irq_nosync(to->clkevt.irq);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	return 0;
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic u64 notrace tegra_read_sched_clock(void)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	return readl_relaxed(timer_reg_base + TIMERUS_CNTR_1US);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#ifdef CONFIG_ARM
17362306a36Sopenharmony_cistatic unsigned long tegra_delay_timer_read_counter_long(void)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	return readl_relaxed(timer_reg_base + TIMERUS_CNTR_1US);
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic struct delay_timer tegra_delay_timer = {
17962306a36Sopenharmony_ci	.read_current_timer = tegra_delay_timer_read_counter_long,
18062306a36Sopenharmony_ci	.freq = TIMER_1MHz,
18162306a36Sopenharmony_ci};
18262306a36Sopenharmony_ci#endif
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic struct timer_of suspend_rtc_to = {
18562306a36Sopenharmony_ci	.flags = TIMER_OF_BASE | TIMER_OF_CLOCK,
18662306a36Sopenharmony_ci};
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/*
18962306a36Sopenharmony_ci * tegra_rtc_read - Reads the Tegra RTC registers
19062306a36Sopenharmony_ci * Care must be taken that this function is not called while the
19162306a36Sopenharmony_ci * tegra_rtc driver could be executing to avoid race conditions
19262306a36Sopenharmony_ci * on the RTC shadow register
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_cistatic u64 tegra_rtc_read_ms(struct clocksource *cs)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	void __iomem *reg_base = timer_of_base(&suspend_rtc_to);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	u32 ms = readl_relaxed(reg_base + RTC_MILLISECONDS);
19962306a36Sopenharmony_ci	u32 s = readl_relaxed(reg_base + RTC_SHADOW_SECONDS);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return (u64)s * MSEC_PER_SEC + ms;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic struct clocksource suspend_rtc_clocksource = {
20562306a36Sopenharmony_ci	.name	= "tegra_suspend_timer",
20662306a36Sopenharmony_ci	.rating	= 200,
20762306a36Sopenharmony_ci	.read	= tegra_rtc_read_ms,
20862306a36Sopenharmony_ci	.mask	= CLOCKSOURCE_MASK(32),
20962306a36Sopenharmony_ci	.flags	= CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic inline unsigned int tegra_base_for_cpu(int cpu, bool tegra20)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	if (tegra20) {
21562306a36Sopenharmony_ci		switch (cpu) {
21662306a36Sopenharmony_ci		case 0:
21762306a36Sopenharmony_ci			return TIMER1_BASE;
21862306a36Sopenharmony_ci		case 1:
21962306a36Sopenharmony_ci			return TIMER2_BASE;
22062306a36Sopenharmony_ci		case 2:
22162306a36Sopenharmony_ci			return TIMER3_BASE;
22262306a36Sopenharmony_ci		default:
22362306a36Sopenharmony_ci			return TIMER4_BASE;
22462306a36Sopenharmony_ci		}
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	return TIMER10_BASE + cpu * 8;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic inline unsigned int tegra_irq_idx_for_cpu(int cpu, bool tegra20)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	if (tegra20)
23362306a36Sopenharmony_ci		return TIMER1_IRQ_IDX + cpu;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return TIMER10_IRQ_IDX + cpu;
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic inline unsigned long tegra_rate_for_timer(struct timer_of *to,
23962306a36Sopenharmony_ci						 bool tegra20)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	/*
24262306a36Sopenharmony_ci	 * TIMER1-9 are fixed to 1MHz, TIMER10-13 are running off the
24362306a36Sopenharmony_ci	 * parent clock.
24462306a36Sopenharmony_ci	 */
24562306a36Sopenharmony_ci	if (tegra20)
24662306a36Sopenharmony_ci		return TIMER_1MHz;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return timer_of_rate(to);
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic int __init tegra_init_timer(struct device_node *np, bool tegra20,
25262306a36Sopenharmony_ci				   int rating)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct timer_of *to;
25562306a36Sopenharmony_ci	int cpu, ret;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	to = this_cpu_ptr(&tegra_to);
25862306a36Sopenharmony_ci	ret = timer_of_init(np, to);
25962306a36Sopenharmony_ci	if (ret)
26062306a36Sopenharmony_ci		goto out;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	timer_reg_base = timer_of_base(to);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	/*
26562306a36Sopenharmony_ci	 * Configure microsecond timers to have 1MHz clock
26662306a36Sopenharmony_ci	 * Config register is 0xqqww, where qq is "dividend", ww is "divisor"
26762306a36Sopenharmony_ci	 * Uses n+1 scheme
26862306a36Sopenharmony_ci	 */
26962306a36Sopenharmony_ci	switch (timer_of_rate(to)) {
27062306a36Sopenharmony_ci	case 12000000:
27162306a36Sopenharmony_ci		usec_config = 0x000b; /* (11+1)/(0+1) */
27262306a36Sopenharmony_ci		break;
27362306a36Sopenharmony_ci	case 12800000:
27462306a36Sopenharmony_ci		usec_config = 0x043f; /* (63+1)/(4+1) */
27562306a36Sopenharmony_ci		break;
27662306a36Sopenharmony_ci	case 13000000:
27762306a36Sopenharmony_ci		usec_config = 0x000c; /* (12+1)/(0+1) */
27862306a36Sopenharmony_ci		break;
27962306a36Sopenharmony_ci	case 16800000:
28062306a36Sopenharmony_ci		usec_config = 0x0453; /* (83+1)/(4+1) */
28162306a36Sopenharmony_ci		break;
28262306a36Sopenharmony_ci	case 19200000:
28362306a36Sopenharmony_ci		usec_config = 0x045f; /* (95+1)/(4+1) */
28462306a36Sopenharmony_ci		break;
28562306a36Sopenharmony_ci	case 26000000:
28662306a36Sopenharmony_ci		usec_config = 0x0019; /* (25+1)/(0+1) */
28762306a36Sopenharmony_ci		break;
28862306a36Sopenharmony_ci	case 38400000:
28962306a36Sopenharmony_ci		usec_config = 0x04bf; /* (191+1)/(4+1) */
29062306a36Sopenharmony_ci		break;
29162306a36Sopenharmony_ci	case 48000000:
29262306a36Sopenharmony_ci		usec_config = 0x002f; /* (47+1)/(0+1) */
29362306a36Sopenharmony_ci		break;
29462306a36Sopenharmony_ci	default:
29562306a36Sopenharmony_ci		ret = -EINVAL;
29662306a36Sopenharmony_ci		goto out;
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	writel_relaxed(usec_config, timer_reg_base + TIMERUS_USEC_CFG);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
30262306a36Sopenharmony_ci		struct timer_of *cpu_to = per_cpu_ptr(&tegra_to, cpu);
30362306a36Sopenharmony_ci		unsigned long flags = IRQF_TIMER | IRQF_NOBALANCING;
30462306a36Sopenharmony_ci		unsigned long rate = tegra_rate_for_timer(to, tegra20);
30562306a36Sopenharmony_ci		unsigned int base = tegra_base_for_cpu(cpu, tegra20);
30662306a36Sopenharmony_ci		unsigned int idx = tegra_irq_idx_for_cpu(cpu, tegra20);
30762306a36Sopenharmony_ci		unsigned int irq = irq_of_parse_and_map(np, idx);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci		if (!irq) {
31062306a36Sopenharmony_ci			pr_err("failed to map irq for cpu%d\n", cpu);
31162306a36Sopenharmony_ci			ret = -EINVAL;
31262306a36Sopenharmony_ci			goto out_irq;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		cpu_to->clkevt.irq = irq;
31662306a36Sopenharmony_ci		cpu_to->clkevt.rating = rating;
31762306a36Sopenharmony_ci		cpu_to->clkevt.cpumask = cpumask_of(cpu);
31862306a36Sopenharmony_ci		cpu_to->of_base.base = timer_reg_base + base;
31962306a36Sopenharmony_ci		cpu_to->of_clk.period = rate / HZ;
32062306a36Sopenharmony_ci		cpu_to->of_clk.rate = rate;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		irq_set_status_flags(cpu_to->clkevt.irq, IRQ_NOAUTOEN);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		ret = request_irq(cpu_to->clkevt.irq, tegra_timer_isr, flags,
32562306a36Sopenharmony_ci				  cpu_to->clkevt.name, &cpu_to->clkevt);
32662306a36Sopenharmony_ci		if (ret) {
32762306a36Sopenharmony_ci			pr_err("failed to set up irq for cpu%d: %d\n",
32862306a36Sopenharmony_ci			       cpu, ret);
32962306a36Sopenharmony_ci			irq_dispose_mapping(cpu_to->clkevt.irq);
33062306a36Sopenharmony_ci			cpu_to->clkevt.irq = 0;
33162306a36Sopenharmony_ci			goto out_irq;
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	sched_clock_register(tegra_read_sched_clock, 32, TIMER_1MHz);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
33862306a36Sopenharmony_ci				    "timer_us", TIMER_1MHz, 300, 32,
33962306a36Sopenharmony_ci				    clocksource_mmio_readl_up);
34062306a36Sopenharmony_ci	if (ret)
34162306a36Sopenharmony_ci		pr_err("failed to register clocksource: %d\n", ret);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci#ifdef CONFIG_ARM
34462306a36Sopenharmony_ci	register_current_timer_delay(&tegra_delay_timer);
34562306a36Sopenharmony_ci#endif
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	ret = cpuhp_setup_state(CPUHP_AP_TEGRA_TIMER_STARTING,
34862306a36Sopenharmony_ci				"AP_TEGRA_TIMER_STARTING", tegra_timer_setup,
34962306a36Sopenharmony_ci				tegra_timer_stop);
35062306a36Sopenharmony_ci	if (ret)
35162306a36Sopenharmony_ci		pr_err("failed to set up cpu hp state: %d\n", ret);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	return ret;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ciout_irq:
35662306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
35762306a36Sopenharmony_ci		struct timer_of *cpu_to;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		cpu_to = per_cpu_ptr(&tegra_to, cpu);
36062306a36Sopenharmony_ci		if (cpu_to->clkevt.irq) {
36162306a36Sopenharmony_ci			free_irq(cpu_to->clkevt.irq, &cpu_to->clkevt);
36262306a36Sopenharmony_ci			irq_dispose_mapping(cpu_to->clkevt.irq);
36362306a36Sopenharmony_ci		}
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	to->of_base.base = timer_reg_base;
36762306a36Sopenharmony_ciout:
36862306a36Sopenharmony_ci	timer_of_cleanup(to);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return ret;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int __init tegra210_init_timer(struct device_node *np)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	/*
37662306a36Sopenharmony_ci	 * Arch-timer can't survive across power cycle of CPU core and
37762306a36Sopenharmony_ci	 * after CPUPORESET signal due to a system design shortcoming,
37862306a36Sopenharmony_ci	 * hence tegra-timer is more preferable on Tegra210.
37962306a36Sopenharmony_ci	 */
38062306a36Sopenharmony_ci	return tegra_init_timer(np, false, 460);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ciTIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_init_timer);
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic int __init tegra20_init_timer(struct device_node *np)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	int rating;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	/*
38962306a36Sopenharmony_ci	 * Tegra20 and Tegra30 have Cortex A9 CPU that has a TWD timer,
39062306a36Sopenharmony_ci	 * that timer runs off the CPU clock and hence is subjected to
39162306a36Sopenharmony_ci	 * a jitter caused by DVFS clock rate changes. Tegra-timer is
39262306a36Sopenharmony_ci	 * more preferable for older Tegra's, while later SoC generations
39362306a36Sopenharmony_ci	 * have arch-timer as a main per-CPU timer and it is not affected
39462306a36Sopenharmony_ci	 * by DVFS changes.
39562306a36Sopenharmony_ci	 */
39662306a36Sopenharmony_ci	if (of_machine_is_compatible("nvidia,tegra20") ||
39762306a36Sopenharmony_ci	    of_machine_is_compatible("nvidia,tegra30"))
39862306a36Sopenharmony_ci		rating = 460;
39962306a36Sopenharmony_ci	else
40062306a36Sopenharmony_ci		rating = 330;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	return tegra_init_timer(np, true, rating);
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ciTIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic int __init tegra20_init_rtc(struct device_node *np)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	int ret;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	ret = timer_of_init(np, &suspend_rtc_to);
41162306a36Sopenharmony_ci	if (ret)
41262306a36Sopenharmony_ci		return ret;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	return clocksource_register_hz(&suspend_rtc_clocksource, 1000);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ciTIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
417