diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2019-06-03 21:59:47 +0300 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2019-06-25 19:49:18 +0200 |
commit | 87bd4c26a6c8e0aa29bf9c77accd16ab8c660a9a (patch) | |
tree | 10f1f0b9a2c635f9b480532d07134226e02f42c2 /drivers/clocksource | |
parent | acb4bb3f37f1fdec00421c4126bf1e2e276a892b (diff) |
clocksource/drivers/tegra: Lower clocksource rating for some Tegra's
Arch-timer is more preferable for a range of Tegra SoC generations as
it has higher precision and is not affect by any kind of problems.
Pointed-out-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-By: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/timer-tegra20.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c index 6a3704142f31..ed1454000ea9 100644 --- a/drivers/clocksource/timer-tegra20.c +++ b/drivers/clocksource/timer-tegra20.c @@ -109,7 +109,6 @@ static DEFINE_PER_CPU(struct timer_of, tegra_to) = { .clkevt = { .name = "tegra_timer", - .rating = 460, .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .set_next_event = tegra_timer_set_next_event, .set_state_shutdown = tegra_timer_shutdown, @@ -219,7 +218,8 @@ static inline unsigned int tegra_irq_idx_for_cpu(int cpu, bool tegra20) return TIMER10_IRQ_IDX + cpu; } -static int __init tegra_init_timer(struct device_node *np, bool tegra20) +static int __init tegra_init_timer(struct device_node *np, bool tegra20, + int rating) { struct timer_of *to; int cpu, ret; @@ -282,6 +282,7 @@ static int __init tegra_init_timer(struct device_node *np, bool tegra20) cpu_to = per_cpu_ptr(&tegra_to, cpu); cpu_to->of_base.base = timer_reg_base + base; + cpu_to->clkevt.rating = rating; cpu_to->clkevt.cpumask = cpumask_of(cpu); cpu_to->clkevt.irq = irq_of_parse_and_map(np, idx); if (!cpu_to->clkevt.irq) { @@ -341,13 +342,34 @@ out: static int __init tegra210_init_timer(struct device_node *np) { - return tegra_init_timer(np, false); + /* + * Arch-timer can't survive across power cycle of CPU core and + * after CPUPORESET signal due to a system design shortcoming, + * hence tegra-timer is more preferable on Tegra210. + */ + return tegra_init_timer(np, false, 460); } TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_init_timer); static int __init tegra20_init_timer(struct device_node *np) { - return tegra_init_timer(np, true); + int rating; + + /* + * Tegra20 and Tegra30 have Cortex A9 CPU that has a TWD timer, + * that timer runs off the CPU clock and hence is subjected to + * a jitter caused by DVFS clock rate changes. Tegra-timer is + * more preferable for older Tegra's, while later SoC generations + * have arch-timer as a main per-CPU timer and it is not affected + * by DVFS changes. + */ + if (of_machine_is_compatible("nvidia,tegra20") || + of_machine_is_compatible("nvidia,tegra30")) + rating = 460; + else + rating = 330; + + return tegra_init_timer(np, true, rating); } TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); |