summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2019-06-03 14:59:39 -0400
committerDaniel Lezcano <daniel.lezcano@linaro.org>2019-06-25 13:49:18 -0400
commitf6d50ec5f85c98d191d8dda032557ab297c14401 (patch)
tree66eb5f9787a15eb64cef24ab62dc9410335a8308 /drivers/clocksource
parent6282edb72bed5324352522d732080d4c1b9dfed6 (diff)
clocksource/drivers/tegra: Support per-CPU timers on all Tegra's
Assign TMR1-4 per-CPU core on 32bit Tegra's in a way it is done for Tegra210. In a result each core can handle its own timer events, less code is unique to ARM64 and Tegra's clock events driver now has higher rating on all Tegra's, replacing the ARM's TWD timer which isn't very accurate due to the clock rate jitter caused by CPU frequency scaling. 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.c120
1 files changed, 43 insertions, 77 deletions
diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c
index 1e7ece279730..4b30ba6228c1 100644
--- a/drivers/clocksource/timer-tegra20.c
+++ b/drivers/clocksource/timer-tegra20.c
@@ -40,13 +40,18 @@
40#define TIMER_PCR_INTR_CLR BIT(30) 40#define TIMER_PCR_INTR_CLR BIT(30)
41 41
42#ifdef CONFIG_ARM 42#ifdef CONFIG_ARM
43#define TIMER_CPU0 0x50 /* TIMER3 */ 43#define TIMER_CPU0 0x00 /* TIMER1 */
44#define TIMER_CPU2 0x50 /* TIMER3 */
45#define TIMER1_IRQ_IDX 0
46#define IRQ_IDX_FOR_CPU(cpu) (TIMER1_IRQ_IDX + cpu)
47#define TIMER_BASE_FOR_CPU(cpu) \
48 (((cpu) & 1) * 8 + ((cpu) < 2 ? TIMER_CPU0 : TIMER_CPU2))
44#else 49#else
45#define TIMER_CPU0 0x90 /* TIMER10 */ 50#define TIMER_CPU0 0x90 /* TIMER10 */
46#define TIMER10_IRQ_IDX 10 51#define TIMER10_IRQ_IDX 10
47#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu) 52#define IRQ_IDX_FOR_CPU(cpu) (TIMER10_IRQ_IDX + cpu)
48#endif
49#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8) 53#define TIMER_BASE_FOR_CPU(cpu) (TIMER_CPU0 + (cpu) * 8)
54#endif
50 55
51static u32 usec_config; 56static u32 usec_config;
52static void __iomem *timer_reg_base; 57static void __iomem *timer_reg_base;
@@ -109,7 +114,6 @@ static void tegra_timer_resume(struct clock_event_device *evt)
109 writel(usec_config, timer_reg_base + TIMERUS_USEC_CFG); 114 writel(usec_config, timer_reg_base + TIMERUS_USEC_CFG);
110} 115}
111 116
112#ifdef CONFIG_ARM64
113static DEFINE_PER_CPU(struct timer_of, tegra_to) = { 117static DEFINE_PER_CPU(struct timer_of, tegra_to) = {
114 .flags = TIMER_OF_CLOCK | TIMER_OF_BASE, 118 .flags = TIMER_OF_CLOCK | TIMER_OF_BASE,
115 119
@@ -150,33 +154,8 @@ static int tegra_timer_stop(unsigned int cpu)
150 154
151 return 0; 155 return 0;
152} 156}
153#else /* CONFIG_ARM */
154static struct timer_of tegra_to = {
155 .flags = TIMER_OF_CLOCK | TIMER_OF_BASE | TIMER_OF_IRQ,
156
157 .clkevt = {
158 .name = "tegra_timer",
159 .rating = 300,
160 .features = CLOCK_EVT_FEAT_ONESHOT |
161 CLOCK_EVT_FEAT_PERIODIC |
162 CLOCK_EVT_FEAT_DYNIRQ,
163 .set_next_event = tegra_timer_set_next_event,
164 .set_state_shutdown = tegra_timer_shutdown,
165 .set_state_periodic = tegra_timer_set_periodic,
166 .set_state_oneshot = tegra_timer_shutdown,
167 .tick_resume = tegra_timer_shutdown,
168 .suspend = tegra_timer_suspend,
169 .resume = tegra_timer_resume,
170 .cpumask = cpu_possible_mask,
171 },
172
173 .of_irq = {
174 .index = 2,
175 .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH,
176 .handler = tegra_timer_isr,
177 },
178};
179 157
158#ifdef CONFIG_ARM
180static u64 notrace tegra_read_sched_clock(void) 159static u64 notrace tegra_read_sched_clock(void)
181{ 160{
182 return readl(timer_reg_base + TIMERUS_CNTR_1US); 161 return readl(timer_reg_base + TIMERUS_CNTR_1US);
@@ -213,10 +192,12 @@ static struct clocksource suspend_rtc_clocksource = {
213}; 192};
214#endif 193#endif
215 194
216static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) 195static int tegra_init_timer(struct device_node *np, bool tegra20)
217{ 196{
218 int ret = 0; 197 struct timer_of *to;
198 int cpu, ret;
219 199
200 to = this_cpu_ptr(&tegra_to);
220 ret = timer_of_init(np, to); 201 ret = timer_of_init(np, to);
221 if (ret < 0) 202 if (ret < 0)
222 goto out; 203 goto out;
@@ -258,29 +239,19 @@ static int tegra_timer_common_init(struct device_node *np, struct timer_of *to)
258 goto out; 239 goto out;
259 } 240 }
260 241
261 writel(usec_config, timer_of_base(to) + TIMERUS_USEC_CFG); 242 writel(usec_config, timer_reg_base + TIMERUS_USEC_CFG);
262
263out:
264 return ret;
265}
266
267#ifdef CONFIG_ARM64
268static int __init tegra_init_timer(struct device_node *np)
269{
270 int cpu, ret = 0;
271 struct timer_of *to;
272
273 to = this_cpu_ptr(&tegra_to);
274 ret = tegra_timer_common_init(np, to);
275 if (ret < 0)
276 goto out;
277 243
278 for_each_possible_cpu(cpu) { 244 for_each_possible_cpu(cpu) {
279 struct timer_of *cpu_to; 245 struct timer_of *cpu_to = per_cpu_ptr(&tegra_to, cpu);
246
247 /*
248 * TIMER1-9 are fixed to 1MHz, TIMER10-13 are running off the
249 * parent clock.
250 */
251 if (tegra20)
252 cpu_to->of_clk.rate = 1000000;
280 253
281 cpu_to = per_cpu_ptr(&tegra_to, cpu);
282 cpu_to->of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(cpu); 254 cpu_to->of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(cpu);
283 cpu_to->of_clk.rate = timer_of_rate(to);
284 cpu_to->clkevt.cpumask = cpumask_of(cpu); 255 cpu_to->clkevt.cpumask = cpumask_of(cpu);
285 cpu_to->clkevt.irq = 256 cpu_to->clkevt.irq =
286 irq_of_parse_and_map(np, IRQ_IDX_FOR_CPU(cpu)); 257 irq_of_parse_and_map(np, IRQ_IDX_FOR_CPU(cpu));
@@ -322,43 +293,39 @@ out:
322 timer_of_cleanup(to); 293 timer_of_cleanup(to);
323 return ret; 294 return ret;
324} 295}
296
297#ifdef CONFIG_ARM64
298static int __init tegra210_init_timer(struct device_node *np)
299{
300 return tegra_init_timer(np, false);
301}
302TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_init_timer);
325#else /* CONFIG_ARM */ 303#else /* CONFIG_ARM */
326static int __init tegra_init_timer(struct device_node *np) 304static int __init tegra20_init_timer(struct device_node *np)
327{ 305{
328 int ret = 0; 306 struct timer_of *to;
307 int err;
329 308
330 ret = tegra_timer_common_init(np, &tegra_to); 309 err = tegra_init_timer(np, true);
331 if (ret < 0) 310 if (err)
332 goto out; 311 return err;
333 312
334 tegra_to.of_base.base = timer_reg_base + TIMER_BASE_FOR_CPU(0); 313 to = this_cpu_ptr(&tegra_to);
335 tegra_to.of_clk.rate = 1000000; /* microsecond timer */
336 314
337 sched_clock_register(tegra_read_sched_clock, 32, 315 sched_clock_register(tegra_read_sched_clock, 32,
338 timer_of_rate(&tegra_to)); 316 timer_of_rate(to));
339 ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, 317 err = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
340 "timer_us", timer_of_rate(&tegra_to), 318 "timer_us", timer_of_rate(to),
341 300, 32, clocksource_mmio_readl_up); 319 300, 32, clocksource_mmio_readl_up);
342 if (ret) { 320 if (err)
343 pr_err("Failed to register clocksource\n"); 321 pr_err("Failed to register clocksource: %d\n", err);
344 goto out;
345 }
346 322
347 tegra_delay_timer.read_current_timer = 323 tegra_delay_timer.read_current_timer =
348 tegra_delay_timer_read_counter_long; 324 tegra_delay_timer_read_counter_long;
349 tegra_delay_timer.freq = timer_of_rate(&tegra_to); 325 tegra_delay_timer.freq = timer_of_rate(to);
350 register_current_timer_delay(&tegra_delay_timer); 326 register_current_timer_delay(&tegra_delay_timer);
351 327
352 clockevents_config_and_register(&tegra_to.clkevt, 328 return 0;
353 timer_of_rate(&tegra_to),
354 0x1,
355 0x1fffffff);
356
357 return ret;
358out:
359 timer_of_cleanup(&tegra_to);
360
361 return ret;
362} 329}
363 330
364static int __init tegra20_init_rtc(struct device_node *np) 331static int __init tegra20_init_rtc(struct device_node *np)
@@ -374,6 +341,5 @@ static int __init tegra20_init_rtc(struct device_node *np)
374 return 0; 341 return 0;
375} 342}
376TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); 343TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
344TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
377#endif 345#endif
378TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra_init_timer);
379TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra_init_timer);