diff options
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/timer-tegra20.c | 120 |
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 | ||
51 | static u32 usec_config; | 56 | static u32 usec_config; |
52 | static void __iomem *timer_reg_base; | 57 | static 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 | ||
113 | static DEFINE_PER_CPU(struct timer_of, tegra_to) = { | 117 | static 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 */ | ||
154 | static 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 | ||
180 | static u64 notrace tegra_read_sched_clock(void) | 159 | static 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 | ||
216 | static int tegra_timer_common_init(struct device_node *np, struct timer_of *to) | 195 | static 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 | |||
263 | out: | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_ARM64 | ||
268 | static 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 | ||
298 | static int __init tegra210_init_timer(struct device_node *np) | ||
299 | { | ||
300 | return tegra_init_timer(np, false); | ||
301 | } | ||
302 | TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra210_init_timer); | ||
325 | #else /* CONFIG_ARM */ | 303 | #else /* CONFIG_ARM */ |
326 | static int __init tegra_init_timer(struct device_node *np) | 304 | static 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; | ||
358 | out: | ||
359 | timer_of_cleanup(&tegra_to); | ||
360 | |||
361 | return ret; | ||
362 | } | 329 | } |
363 | 330 | ||
364 | static int __init tegra20_init_rtc(struct device_node *np) | 331 | static 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 | } |
376 | TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); | 343 | TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); |
344 | TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); | ||
377 | #endif | 345 | #endif |
378 | TIMER_OF_DECLARE(tegra210_timer, "nvidia,tegra210-timer", tegra_init_timer); | ||
379 | TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra_init_timer); | ||