diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index c64d543d64bf..ffe9d1c6b588 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -67,7 +67,7 @@ static int arch_timer_ppi[MAX_TIMER_PPI]; | |||
67 | 67 | ||
68 | static struct clock_event_device __percpu *arch_timer_evt; | 68 | static struct clock_event_device __percpu *arch_timer_evt; |
69 | 69 | ||
70 | static bool arch_timer_use_virtual = true; | 70 | static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; |
71 | static bool arch_timer_c3stop; | 71 | static bool arch_timer_c3stop; |
72 | static bool arch_timer_mem_use_virtual; | 72 | static bool arch_timer_mem_use_virtual; |
73 | 73 | ||
@@ -263,14 +263,20 @@ static void __arch_timer_setup(unsigned type, | |||
263 | clk->name = "arch_sys_timer"; | 263 | clk->name = "arch_sys_timer"; |
264 | clk->rating = 450; | 264 | clk->rating = 450; |
265 | clk->cpumask = cpumask_of(smp_processor_id()); | 265 | clk->cpumask = cpumask_of(smp_processor_id()); |
266 | if (arch_timer_use_virtual) { | 266 | clk->irq = arch_timer_ppi[arch_timer_uses_ppi]; |
267 | clk->irq = arch_timer_ppi[VIRT_PPI]; | 267 | switch (arch_timer_uses_ppi) { |
268 | case VIRT_PPI: | ||
268 | clk->set_state_shutdown = arch_timer_shutdown_virt; | 269 | clk->set_state_shutdown = arch_timer_shutdown_virt; |
269 | clk->set_next_event = arch_timer_set_next_event_virt; | 270 | clk->set_next_event = arch_timer_set_next_event_virt; |
270 | } else { | 271 | break; |
271 | clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; | 272 | case PHYS_SECURE_PPI: |
273 | case PHYS_NONSECURE_PPI: | ||
274 | case HYP_PPI: | ||
272 | clk->set_state_shutdown = arch_timer_shutdown_phys; | 275 | clk->set_state_shutdown = arch_timer_shutdown_phys; |
273 | clk->set_next_event = arch_timer_set_next_event_phys; | 276 | clk->set_next_event = arch_timer_set_next_event_phys; |
277 | break; | ||
278 | default: | ||
279 | BUG(); | ||
274 | } | 280 | } |
275 | } else { | 281 | } else { |
276 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; | 282 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; |
@@ -338,17 +344,20 @@ static void arch_counter_set_user_access(void) | |||
338 | arch_timer_set_cntkctl(cntkctl); | 344 | arch_timer_set_cntkctl(cntkctl); |
339 | } | 345 | } |
340 | 346 | ||
347 | static bool arch_timer_has_nonsecure_ppi(void) | ||
348 | { | ||
349 | return (arch_timer_uses_ppi == PHYS_SECURE_PPI && | ||
350 | arch_timer_ppi[PHYS_NONSECURE_PPI]); | ||
351 | } | ||
352 | |||
341 | static int arch_timer_setup(struct clock_event_device *clk) | 353 | static int arch_timer_setup(struct clock_event_device *clk) |
342 | { | 354 | { |
343 | __arch_timer_setup(ARCH_CP15_TIMER, clk); | 355 | __arch_timer_setup(ARCH_CP15_TIMER, clk); |
344 | 356 | ||
345 | if (arch_timer_use_virtual) | 357 | enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); |
346 | enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0); | 358 | |
347 | else { | 359 | if (arch_timer_has_nonsecure_ppi()) |
348 | enable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 0); | 360 | enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); |
349 | if (arch_timer_ppi[PHYS_NONSECURE_PPI]) | ||
350 | enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0); | ||
351 | } | ||
352 | 361 | ||
353 | arch_counter_set_user_access(); | 362 | arch_counter_set_user_access(); |
354 | if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM)) | 363 | if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM)) |
@@ -390,7 +399,7 @@ static void arch_timer_banner(unsigned type) | |||
390 | (unsigned long)arch_timer_rate / 1000000, | 399 | (unsigned long)arch_timer_rate / 1000000, |
391 | (unsigned long)(arch_timer_rate / 10000) % 100, | 400 | (unsigned long)(arch_timer_rate / 10000) % 100, |
392 | type & ARCH_CP15_TIMER ? | 401 | type & ARCH_CP15_TIMER ? |
393 | arch_timer_use_virtual ? "virt" : "phys" : | 402 | (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : |
394 | "", | 403 | "", |
395 | type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", | 404 | type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", |
396 | type & ARCH_MEM_TIMER ? | 405 | type & ARCH_MEM_TIMER ? |
@@ -460,7 +469,7 @@ static void __init arch_counter_register(unsigned type) | |||
460 | 469 | ||
461 | /* Register the CP15 based counter if we have one */ | 470 | /* Register the CP15 based counter if we have one */ |
462 | if (type & ARCH_CP15_TIMER) { | 471 | if (type & ARCH_CP15_TIMER) { |
463 | if (IS_ENABLED(CONFIG_ARM64) || arch_timer_use_virtual) | 472 | if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI) |
464 | arch_timer_read_counter = arch_counter_get_cntvct; | 473 | arch_timer_read_counter = arch_counter_get_cntvct; |
465 | else | 474 | else |
466 | arch_timer_read_counter = arch_counter_get_cntpct; | 475 | arch_timer_read_counter = arch_counter_get_cntpct; |
@@ -490,13 +499,9 @@ static void arch_timer_stop(struct clock_event_device *clk) | |||
490 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", | 499 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", |
491 | clk->irq, smp_processor_id()); | 500 | clk->irq, smp_processor_id()); |
492 | 501 | ||
493 | if (arch_timer_use_virtual) | 502 | disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]); |
494 | disable_percpu_irq(arch_timer_ppi[VIRT_PPI]); | 503 | if (arch_timer_has_nonsecure_ppi()) |
495 | else { | 504 | disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); |
496 | disable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI]); | ||
497 | if (arch_timer_ppi[PHYS_NONSECURE_PPI]) | ||
498 | disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); | ||
499 | } | ||
500 | 505 | ||
501 | clk->set_state_shutdown(clk); | 506 | clk->set_state_shutdown(clk); |
502 | } | 507 | } |
@@ -562,12 +567,14 @@ static int __init arch_timer_register(void) | |||
562 | goto out; | 567 | goto out; |
563 | } | 568 | } |
564 | 569 | ||
565 | if (arch_timer_use_virtual) { | 570 | ppi = arch_timer_ppi[arch_timer_uses_ppi]; |
566 | ppi = arch_timer_ppi[VIRT_PPI]; | 571 | switch (arch_timer_uses_ppi) { |
572 | case VIRT_PPI: | ||
567 | err = request_percpu_irq(ppi, arch_timer_handler_virt, | 573 | err = request_percpu_irq(ppi, arch_timer_handler_virt, |
568 | "arch_timer", arch_timer_evt); | 574 | "arch_timer", arch_timer_evt); |
569 | } else { | 575 | break; |
570 | ppi = arch_timer_ppi[PHYS_SECURE_PPI]; | 576 | case PHYS_SECURE_PPI: |
577 | case PHYS_NONSECURE_PPI: | ||
571 | err = request_percpu_irq(ppi, arch_timer_handler_phys, | 578 | err = request_percpu_irq(ppi, arch_timer_handler_phys, |
572 | "arch_timer", arch_timer_evt); | 579 | "arch_timer", arch_timer_evt); |
573 | if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { | 580 | if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { |
@@ -578,6 +585,13 @@ static int __init arch_timer_register(void) | |||
578 | free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], | 585 | free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], |
579 | arch_timer_evt); | 586 | arch_timer_evt); |
580 | } | 587 | } |
588 | break; | ||
589 | case HYP_PPI: | ||
590 | err = request_percpu_irq(ppi, arch_timer_handler_phys, | ||
591 | "arch_timer", arch_timer_evt); | ||
592 | break; | ||
593 | default: | ||
594 | BUG(); | ||
581 | } | 595 | } |
582 | 596 | ||
583 | if (err) { | 597 | if (err) { |
@@ -602,15 +616,10 @@ static int __init arch_timer_register(void) | |||
602 | out_unreg_notify: | 616 | out_unreg_notify: |
603 | unregister_cpu_notifier(&arch_timer_cpu_nb); | 617 | unregister_cpu_notifier(&arch_timer_cpu_nb); |
604 | out_free_irq: | 618 | out_free_irq: |
605 | if (arch_timer_use_virtual) | 619 | free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); |
606 | free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt); | 620 | if (arch_timer_has_nonsecure_ppi()) |
607 | else { | 621 | free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], |
608 | free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], | ||
609 | arch_timer_evt); | 622 | arch_timer_evt); |
610 | if (arch_timer_ppi[PHYS_NONSECURE_PPI]) | ||
611 | free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], | ||
612 | arch_timer_evt); | ||
613 | } | ||
614 | 623 | ||
615 | out_free: | 624 | out_free: |
616 | free_percpu(arch_timer_evt); | 625 | free_percpu(arch_timer_evt); |
@@ -697,12 +706,25 @@ static void __init arch_timer_init(void) | |||
697 | * | 706 | * |
698 | * If no interrupt provided for virtual timer, we'll have to | 707 | * If no interrupt provided for virtual timer, we'll have to |
699 | * stick to the physical timer. It'd better be accessible... | 708 | * stick to the physical timer. It'd better be accessible... |
709 | * | ||
710 | * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE | ||
711 | * accesses to CNTP_*_EL1 registers are silently redirected to | ||
712 | * their CNTHP_*_EL2 counterparts, and use a different PPI | ||
713 | * number. | ||
700 | */ | 714 | */ |
701 | if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { | 715 | if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { |
702 | arch_timer_use_virtual = false; | 716 | bool has_ppi; |
717 | |||
718 | if (is_kernel_in_hyp_mode()) { | ||
719 | arch_timer_uses_ppi = HYP_PPI; | ||
720 | has_ppi = !!arch_timer_ppi[HYP_PPI]; | ||
721 | } else { | ||
722 | arch_timer_uses_ppi = PHYS_SECURE_PPI; | ||
723 | has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] || | ||
724 | !!arch_timer_ppi[PHYS_NONSECURE_PPI]); | ||
725 | } | ||
703 | 726 | ||
704 | if (!arch_timer_ppi[PHYS_SECURE_PPI] || | 727 | if (!has_ppi) { |
705 | !arch_timer_ppi[PHYS_NONSECURE_PPI]) { | ||
706 | pr_warn("arch_timer: No interrupt available, giving up\n"); | 728 | pr_warn("arch_timer: No interrupt available, giving up\n"); |
707 | return; | 729 | return; |
708 | } | 730 | } |
@@ -735,7 +757,7 @@ static void __init arch_timer_of_init(struct device_node *np) | |||
735 | */ | 757 | */ |
736 | if (IS_ENABLED(CONFIG_ARM) && | 758 | if (IS_ENABLED(CONFIG_ARM) && |
737 | of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) | 759 | of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) |
738 | arch_timer_use_virtual = false; | 760 | arch_timer_uses_ppi = PHYS_SECURE_PPI; |
739 | 761 | ||
740 | arch_timer_init(); | 762 | arch_timer_init(); |
741 | } | 763 | } |