18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2010 Google, Inc. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: 68c2ecf20Sopenharmony_ci * Colin Cross <ccross@google.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "tegra-timer: " fmt 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/clockchips.h> 138c2ecf20Sopenharmony_ci#include <linux/cpu.h> 148c2ecf20Sopenharmony_ci#include <linux/cpumask.h> 158c2ecf20Sopenharmony_ci#include <linux/delay.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/of_address.h> 198c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 208c2ecf20Sopenharmony_ci#include <linux/percpu.h> 218c2ecf20Sopenharmony_ci#include <linux/sched_clock.h> 228c2ecf20Sopenharmony_ci#include <linux/time.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "timer-of.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define RTC_SECONDS 0x08 278c2ecf20Sopenharmony_ci#define RTC_SHADOW_SECONDS 0x0c 288c2ecf20Sopenharmony_ci#define RTC_MILLISECONDS 0x10 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define TIMERUS_CNTR_1US 0x10 318c2ecf20Sopenharmony_ci#define TIMERUS_USEC_CFG 0x14 328c2ecf20Sopenharmony_ci#define TIMERUS_CNTR_FREEZE 0x4c 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define TIMER_PTV 0x0 358c2ecf20Sopenharmony_ci#define TIMER_PTV_EN BIT(31) 368c2ecf20Sopenharmony_ci#define TIMER_PTV_PER BIT(30) 378c2ecf20Sopenharmony_ci#define TIMER_PCR 0x4 388c2ecf20Sopenharmony_ci#define TIMER_PCR_INTR_CLR BIT(30) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define TIMER1_BASE 0x00 418c2ecf20Sopenharmony_ci#define TIMER2_BASE 0x08 428c2ecf20Sopenharmony_ci#define TIMER3_BASE 0x50 438c2ecf20Sopenharmony_ci#define TIMER4_BASE 0x58 448c2ecf20Sopenharmony_ci#define TIMER10_BASE 0x90 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define TIMER1_IRQ_IDX 0 478c2ecf20Sopenharmony_ci#define TIMER10_IRQ_IDX 10 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define TIMER_1MHz 1000000 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic u32 usec_config; 528c2ecf20Sopenharmony_cistatic void __iomem *timer_reg_base; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic int tegra_timer_set_next_event(unsigned long cycles, 558c2ecf20Sopenharmony_ci struct clock_event_device *evt) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(to_timer_of(evt)); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* 608c2ecf20Sopenharmony_ci * Tegra's timer uses n+1 scheme for the counter, i.e. timer will 618c2ecf20Sopenharmony_ci * fire after one tick if 0 is loaded. 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * The minimum and maximum numbers of oneshot ticks are defined 648c2ecf20Sopenharmony_ci * by clockevents_config_and_register(1, 0x1fffffff + 1) invocation 658c2ecf20Sopenharmony_ci * below in the code. Hence the cycles (ticks) can't be outside of 668c2ecf20Sopenharmony_ci * a range supportable by hardware. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci writel_relaxed(TIMER_PTV_EN | (cycles - 1), reg_base + TIMER_PTV); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic int tegra_timer_shutdown(struct clock_event_device *evt) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(to_timer_of(evt)); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci writel_relaxed(0, reg_base + TIMER_PTV); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic int tegra_timer_set_periodic(struct clock_event_device *evt) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(to_timer_of(evt)); 858c2ecf20Sopenharmony_ci unsigned long period = timer_of_period(to_timer_of(evt)); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci writel_relaxed(TIMER_PTV_EN | TIMER_PTV_PER | (period - 1), 888c2ecf20Sopenharmony_ci reg_base + TIMER_PTV); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic irqreturn_t tegra_timer_isr(int irq, void *dev_id) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct clock_event_device *evt = dev_id; 968c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(to_timer_of(evt)); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci writel_relaxed(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); 998c2ecf20Sopenharmony_ci evt->event_handler(evt); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic void tegra_timer_suspend(struct clock_event_device *evt) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(to_timer_of(evt)); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci writel_relaxed(TIMER_PCR_INTR_CLR, reg_base + TIMER_PCR); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic void tegra_timer_resume(struct clock_event_device *evt) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci writel_relaxed(usec_config, timer_reg_base + TIMERUS_USEC_CFG); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct timer_of, tegra_to) = { 1178c2ecf20Sopenharmony_ci .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci .clkevt = { 1208c2ecf20Sopenharmony_ci .name = "tegra_timer", 1218c2ecf20Sopenharmony_ci .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 1228c2ecf20Sopenharmony_ci .set_next_event = tegra_timer_set_next_event, 1238c2ecf20Sopenharmony_ci .set_state_shutdown = tegra_timer_shutdown, 1248c2ecf20Sopenharmony_ci .set_state_periodic = tegra_timer_set_periodic, 1258c2ecf20Sopenharmony_ci .set_state_oneshot = tegra_timer_shutdown, 1268c2ecf20Sopenharmony_ci .tick_resume = tegra_timer_shutdown, 1278c2ecf20Sopenharmony_ci .suspend = tegra_timer_suspend, 1288c2ecf20Sopenharmony_ci .resume = tegra_timer_resume, 1298c2ecf20Sopenharmony_ci }, 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic int tegra_timer_setup(unsigned int cpu) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct timer_of *to = per_cpu_ptr(&tegra_to, cpu); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci writel_relaxed(0, timer_of_base(to) + TIMER_PTV); 1378c2ecf20Sopenharmony_ci writel_relaxed(TIMER_PCR_INTR_CLR, timer_of_base(to) + TIMER_PCR); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci irq_force_affinity(to->clkevt.irq, cpumask_of(cpu)); 1408c2ecf20Sopenharmony_ci enable_irq(to->clkevt.irq); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* 1438c2ecf20Sopenharmony_ci * Tegra's timer uses n+1 scheme for the counter, i.e. timer will 1448c2ecf20Sopenharmony_ci * fire after one tick if 0 is loaded and thus minimum number of 1458c2ecf20Sopenharmony_ci * ticks is 1. In result both of the clocksource's tick limits are 1468c2ecf20Sopenharmony_ci * higher than a minimum and maximum that hardware register can 1478c2ecf20Sopenharmony_ci * take by 1, this is then taken into account by set_next_event 1488c2ecf20Sopenharmony_ci * callback. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ci clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 1518c2ecf20Sopenharmony_ci 1, /* min */ 1528c2ecf20Sopenharmony_ci 0x1fffffff + 1); /* max 29 bits + 1 */ 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return 0; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic int tegra_timer_stop(unsigned int cpu) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct timer_of *to = per_cpu_ptr(&tegra_to, cpu); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci to->clkevt.set_state_shutdown(&to->clkevt); 1628c2ecf20Sopenharmony_ci disable_irq_nosync(to->clkevt.irq); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci return 0; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic u64 notrace tegra_read_sched_clock(void) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci return readl_relaxed(timer_reg_base + TIMERUS_CNTR_1US); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM 1738c2ecf20Sopenharmony_cistatic unsigned long tegra_delay_timer_read_counter_long(void) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci return readl_relaxed(timer_reg_base + TIMERUS_CNTR_1US); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic struct delay_timer tegra_delay_timer = { 1798c2ecf20Sopenharmony_ci .read_current_timer = tegra_delay_timer_read_counter_long, 1808c2ecf20Sopenharmony_ci .freq = TIMER_1MHz, 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci#endif 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic struct timer_of suspend_rtc_to = { 1858c2ecf20Sopenharmony_ci .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/* 1898c2ecf20Sopenharmony_ci * tegra_rtc_read - Reads the Tegra RTC registers 1908c2ecf20Sopenharmony_ci * Care must be taken that this function is not called while the 1918c2ecf20Sopenharmony_ci * tegra_rtc driver could be executing to avoid race conditions 1928c2ecf20Sopenharmony_ci * on the RTC shadow register 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_cistatic u64 tegra_rtc_read_ms(struct clocksource *cs) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci void __iomem *reg_base = timer_of_base(&suspend_rtc_to); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci u32 ms = readl_relaxed(reg_base + RTC_MILLISECONDS); 1998c2ecf20Sopenharmony_ci u32 s = readl_relaxed(reg_base + RTC_SHADOW_SECONDS); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return (u64)s * MSEC_PER_SEC + ms; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic struct clocksource suspend_rtc_clocksource = { 2058c2ecf20Sopenharmony_ci .name = "tegra_suspend_timer", 2068c2ecf20Sopenharmony_ci .rating = 200, 2078c2ecf20Sopenharmony_ci .read = tegra_rtc_read_ms, 2088c2ecf20Sopenharmony_ci .mask = CLOCKSOURCE_MASK(32), 2098c2ecf20Sopenharmony_ci .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic inline unsigned int tegra_base_for_cpu(int cpu, bool tegra20) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci if (tegra20) { 2158c2ecf20Sopenharmony_ci switch (cpu) { 2168c2ecf20Sopenharmony_ci case 0: 2178c2ecf20Sopenharmony_ci return TIMER1_BASE; 2188c2ecf20Sopenharmony_ci case 1: 2198c2ecf20Sopenharmony_ci return TIMER2_BASE; 2208c2ecf20Sopenharmony_ci case 2: 2218c2ecf20Sopenharmony_ci return TIMER3_BASE; 2228c2ecf20Sopenharmony_ci default: 2238c2ecf20Sopenharmony_ci return TIMER4_BASE; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return TIMER10_BASE + cpu * 8; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic inline unsigned int tegra_irq_idx_for_cpu(int cpu, bool tegra20) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci if (tegra20) 2338c2ecf20Sopenharmony_ci return TIMER1_IRQ_IDX + cpu; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci return TIMER10_IRQ_IDX + cpu; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic inline unsigned long tegra_rate_for_timer(struct timer_of *to, 2398c2ecf20Sopenharmony_ci bool tegra20) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci /* 2428c2ecf20Sopenharmony_ci * TIMER1-9 are fixed to 1MHz, TIMER10-13 are running off the 2438c2ecf20Sopenharmony_ci * parent clock. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci if (tegra20) 2468c2ecf20Sopenharmony_ci return TIMER_1MHz; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return timer_of_rate(to); 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic int __init tegra_init_timer(struct device_node *np, bool tegra20, 2528c2ecf20Sopenharmony_ci int rating) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct timer_of *to; 2558c2ecf20Sopenharmony_ci int cpu, ret; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci to = this_cpu_ptr(&tegra_to); 2588c2ecf20Sopenharmony_ci ret = timer_of_init(np, to); 2598c2ecf20Sopenharmony_ci if (ret) 2608c2ecf20Sopenharmony_ci goto out; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci timer_reg_base = timer_of_base(to); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* 2658c2ecf20Sopenharmony_ci * Configure microsecond timers to have 1MHz clock 2668c2ecf20Sopenharmony_ci * Config register is 0xqqww, where qq is "dividend", ww is "divisor" 2678c2ecf20Sopenharmony_ci * Uses n+1 scheme 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_ci switch (timer_of_rate(to)) { 2708c2ecf20Sopenharmony_ci case 12000000: 2718c2ecf20Sopenharmony_ci usec_config = 0x000b; /* (11+1)/(0+1) */ 2728c2ecf20Sopenharmony_ci break; 2738c2ecf20Sopenharmony_ci case 12800000: 2748c2ecf20Sopenharmony_ci usec_config = 0x043f; /* (63+1)/(4+1) */ 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci case 13000000: 2778c2ecf20Sopenharmony_ci usec_config = 0x000c; /* (12+1)/(0+1) */ 2788c2ecf20Sopenharmony_ci break; 2798c2ecf20Sopenharmony_ci case 16800000: 2808c2ecf20Sopenharmony_ci usec_config = 0x0453; /* (83+1)/(4+1) */ 2818c2ecf20Sopenharmony_ci break; 2828c2ecf20Sopenharmony_ci case 19200000: 2838c2ecf20Sopenharmony_ci usec_config = 0x045f; /* (95+1)/(4+1) */ 2848c2ecf20Sopenharmony_ci break; 2858c2ecf20Sopenharmony_ci case 26000000: 2868c2ecf20Sopenharmony_ci usec_config = 0x0019; /* (25+1)/(0+1) */ 2878c2ecf20Sopenharmony_ci break; 2888c2ecf20Sopenharmony_ci case 38400000: 2898c2ecf20Sopenharmony_ci usec_config = 0x04bf; /* (191+1)/(4+1) */ 2908c2ecf20Sopenharmony_ci break; 2918c2ecf20Sopenharmony_ci case 48000000: 2928c2ecf20Sopenharmony_ci usec_config = 0x002f; /* (47+1)/(0+1) */ 2938c2ecf20Sopenharmony_ci break; 2948c2ecf20Sopenharmony_ci default: 2958c2ecf20Sopenharmony_ci ret = -EINVAL; 2968c2ecf20Sopenharmony_ci goto out; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci writel_relaxed(usec_config, timer_reg_base + TIMERUS_USEC_CFG); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 3028c2ecf20Sopenharmony_ci struct timer_of *cpu_to = per_cpu_ptr(&tegra_to, cpu); 3038c2ecf20Sopenharmony_ci unsigned long flags = IRQF_TIMER | IRQF_NOBALANCING; 3048c2ecf20Sopenharmony_ci unsigned long rate = tegra_rate_for_timer(to, tegra20); 3058c2ecf20Sopenharmony_ci unsigned int base = tegra_base_for_cpu(cpu, tegra20); 3068c2ecf20Sopenharmony_ci unsigned int idx = tegra_irq_idx_for_cpu(cpu, tegra20); 3078c2ecf20Sopenharmony_ci unsigned int irq = irq_of_parse_and_map(np, idx); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (!irq) { 3108c2ecf20Sopenharmony_ci pr_err("failed to map irq for cpu%d\n", cpu); 3118c2ecf20Sopenharmony_ci ret = -EINVAL; 3128c2ecf20Sopenharmony_ci goto out_irq; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci cpu_to->clkevt.irq = irq; 3168c2ecf20Sopenharmony_ci cpu_to->clkevt.rating = rating; 3178c2ecf20Sopenharmony_ci cpu_to->clkevt.cpumask = cpumask_of(cpu); 3188c2ecf20Sopenharmony_ci cpu_to->of_base.base = timer_reg_base + base; 3198c2ecf20Sopenharmony_ci cpu_to->of_clk.period = rate / HZ; 3208c2ecf20Sopenharmony_ci cpu_to->of_clk.rate = rate; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci irq_set_status_flags(cpu_to->clkevt.irq, IRQ_NOAUTOEN); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ret = request_irq(cpu_to->clkevt.irq, tegra_timer_isr, flags, 3258c2ecf20Sopenharmony_ci cpu_to->clkevt.name, &cpu_to->clkevt); 3268c2ecf20Sopenharmony_ci if (ret) { 3278c2ecf20Sopenharmony_ci pr_err("failed to set up irq for cpu%d: %d\n", 3288c2ecf20Sopenharmony_ci cpu, ret); 3298c2ecf20Sopenharmony_ci irq_dispose_mapping(cpu_to->clkevt.irq); 3308c2ecf20Sopenharmony_ci cpu_to->clkevt.irq = 0; 3318c2ecf20Sopenharmony_ci goto out_irq; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci sched_clock_register(tegra_read_sched_clock, 32, TIMER_1MHz); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, 3388c2ecf20Sopenharmony_ci "timer_us", TIMER_1MHz, 300, 32, 3398c2ecf20Sopenharmony_ci clocksource_mmio_readl_up); 3408c2ecf20Sopenharmony_ci if (ret) 3418c2ecf20Sopenharmony_ci pr_err("failed to register clocksource: %d\n", ret); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM 3448c2ecf20Sopenharmony_ci register_current_timer_delay(&tegra_delay_timer); 3458c2ecf20Sopenharmony_ci#endif 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci ret = cpuhp_setup_state(CPUHP_AP_TEGRA_TIMER_STARTING, 3488c2ecf20Sopenharmony_ci "AP_TEGRA_TIMER_STARTING", tegra_timer_setup, 3498c2ecf20Sopenharmony_ci tegra_timer_stop); 3508c2ecf20Sopenharmony_ci if (ret) 3518c2ecf20Sopenharmony_ci pr_err("failed to set up cpu hp state: %d\n", ret); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci return ret; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ciout_irq: 3568c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) { 3578c2ecf20Sopenharmony_ci struct timer_of *cpu_to; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci cpu_to = per_cpu_ptr(&tegra_to, cpu); 3608c2ecf20Sopenharmony_ci if (cpu_to->clkevt.irq) { 3618c2ecf20Sopenharmony_ci free_irq(cpu_to->clkevt.irq, &cpu_to->clkevt); 3628c2ecf20Sopenharmony_ci irq_dispose_mapping(cpu_to->clkevt.irq); 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci to->of_base.base = timer_reg_base; 3678c2ecf20Sopenharmony_ciout: 3688c2ecf20Sopenharmony_ci timer_of_cleanup(to); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci return ret; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic int __init tegra210_init_timer(struct device_node *np) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci /* 3768c2ecf20Sopenharmony_ci * Arch-timer can't survive across power cycle of CPU core and 3778c2ecf20Sopenharmony_ci * after CPUPORESET signal due to a system design shortcoming, 3788c2ecf20Sopenharmony_ci * hence tegra-timer is more preferable on Tegra210. 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_ci return tegra_init_timer(np, false, 460); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ciTIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_init_timer); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic int __init tegra20_init_timer(struct device_node *np) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci int rating; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci /* 3898c2ecf20Sopenharmony_ci * Tegra20 and Tegra30 have Cortex A9 CPU that has a TWD timer, 3908c2ecf20Sopenharmony_ci * that timer runs off the CPU clock and hence is subjected to 3918c2ecf20Sopenharmony_ci * a jitter caused by DVFS clock rate changes. Tegra-timer is 3928c2ecf20Sopenharmony_ci * more preferable for older Tegra's, while later SoC generations 3938c2ecf20Sopenharmony_ci * have arch-timer as a main per-CPU timer and it is not affected 3948c2ecf20Sopenharmony_ci * by DVFS changes. 3958c2ecf20Sopenharmony_ci */ 3968c2ecf20Sopenharmony_ci if (of_machine_is_compatible("nvidia,tegra20") || 3978c2ecf20Sopenharmony_ci of_machine_is_compatible("nvidia,tegra30")) 3988c2ecf20Sopenharmony_ci rating = 460; 3998c2ecf20Sopenharmony_ci else 4008c2ecf20Sopenharmony_ci rating = 330; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci return tegra_init_timer(np, true, rating); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ciTIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic int __init tegra20_init_rtc(struct device_node *np) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci int ret; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci ret = timer_of_init(np, &suspend_rtc_to); 4118c2ecf20Sopenharmony_ci if (ret) 4128c2ecf20Sopenharmony_ci return ret; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci return clocksource_register_hz(&suspend_rtc_clocksource, 1000); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ciTIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); 417