diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 46 |
1 files changed, 8 insertions, 38 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index da11a9508b77..b2a88a64aab4 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -598,36 +598,12 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t | |||
598 | local ? "local" : "global", wa->desc); | 598 | local ? "local" : "global", wa->desc); |
599 | } | 599 | } |
600 | 600 | ||
601 | #define erratum_handler(fn, r, ...) \ | ||
602 | ({ \ | ||
603 | bool __val; \ | ||
604 | if (needs_unstable_timer_counter_workaround()) { \ | ||
605 | const struct arch_timer_erratum_workaround *__wa; \ | ||
606 | __wa = __this_cpu_read(timer_unstable_counter_workaround); \ | ||
607 | if (__wa && __wa->fn) { \ | ||
608 | r = __wa->fn(__VA_ARGS__); \ | ||
609 | __val = true; \ | ||
610 | } else { \ | ||
611 | __val = false; \ | ||
612 | } \ | ||
613 | } else { \ | ||
614 | __val = false; \ | ||
615 | } \ | ||
616 | __val; \ | ||
617 | }) | ||
618 | |||
619 | static bool arch_timer_this_cpu_has_cntvct_wa(void) | 601 | static bool arch_timer_this_cpu_has_cntvct_wa(void) |
620 | { | 602 | { |
621 | const struct arch_timer_erratum_workaround *wa; | 603 | return has_erratum_handler(read_cntvct_el0); |
622 | |||
623 | wa = __this_cpu_read(timer_unstable_counter_workaround); | ||
624 | return wa && wa->read_cntvct_el0; | ||
625 | } | 604 | } |
626 | #else | 605 | #else |
627 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) | 606 | #define arch_timer_check_ool_workaround(t,a) do { } while(0) |
628 | #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) | ||
629 | #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) | ||
630 | #define erratum_handler(fn, r, ...) ({false;}) | ||
631 | #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) | 607 | #define arch_timer_this_cpu_has_cntvct_wa() ({false;}) |
632 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ | 608 | #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ |
633 | 609 | ||
@@ -721,11 +697,6 @@ static __always_inline void set_next_event(const int access, unsigned long evt, | |||
721 | static int arch_timer_set_next_event_virt(unsigned long evt, | 697 | static int arch_timer_set_next_event_virt(unsigned long evt, |
722 | struct clock_event_device *clk) | 698 | struct clock_event_device *clk) |
723 | { | 699 | { |
724 | int ret; | ||
725 | |||
726 | if (erratum_handler(set_next_event_virt, ret, evt, clk)) | ||
727 | return ret; | ||
728 | |||
729 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); | 700 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); |
730 | return 0; | 701 | return 0; |
731 | } | 702 | } |
@@ -733,11 +704,6 @@ static int arch_timer_set_next_event_virt(unsigned long evt, | |||
733 | static int arch_timer_set_next_event_phys(unsigned long evt, | 704 | static int arch_timer_set_next_event_phys(unsigned long evt, |
734 | struct clock_event_device *clk) | 705 | struct clock_event_device *clk) |
735 | { | 706 | { |
736 | int ret; | ||
737 | |||
738 | if (erratum_handler(set_next_event_phys, ret, evt, clk)) | ||
739 | return ret; | ||
740 | |||
741 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); | 707 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); |
742 | return 0; | 708 | return 0; |
743 | } | 709 | } |
@@ -762,6 +728,10 @@ static void __arch_timer_setup(unsigned type, | |||
762 | clk->features = CLOCK_EVT_FEAT_ONESHOT; | 728 | clk->features = CLOCK_EVT_FEAT_ONESHOT; |
763 | 729 | ||
764 | if (type == ARCH_TIMER_TYPE_CP15) { | 730 | if (type == ARCH_TIMER_TYPE_CP15) { |
731 | typeof(clk->set_next_event) sne; | ||
732 | |||
733 | arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); | ||
734 | |||
765 | if (arch_timer_c3stop) | 735 | if (arch_timer_c3stop) |
766 | clk->features |= CLOCK_EVT_FEAT_C3STOP; | 736 | clk->features |= CLOCK_EVT_FEAT_C3STOP; |
767 | clk->name = "arch_sys_timer"; | 737 | clk->name = "arch_sys_timer"; |
@@ -772,20 +742,20 @@ static void __arch_timer_setup(unsigned type, | |||
772 | case ARCH_TIMER_VIRT_PPI: | 742 | case ARCH_TIMER_VIRT_PPI: |
773 | clk->set_state_shutdown = arch_timer_shutdown_virt; | 743 | clk->set_state_shutdown = arch_timer_shutdown_virt; |
774 | clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; | 744 | clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; |
775 | clk->set_next_event = arch_timer_set_next_event_virt; | 745 | sne = erratum_handler(set_next_event_virt); |
776 | break; | 746 | break; |
777 | case ARCH_TIMER_PHYS_SECURE_PPI: | 747 | case ARCH_TIMER_PHYS_SECURE_PPI: |
778 | case ARCH_TIMER_PHYS_NONSECURE_PPI: | 748 | case ARCH_TIMER_PHYS_NONSECURE_PPI: |
779 | case ARCH_TIMER_HYP_PPI: | 749 | case ARCH_TIMER_HYP_PPI: |
780 | clk->set_state_shutdown = arch_timer_shutdown_phys; | 750 | clk->set_state_shutdown = arch_timer_shutdown_phys; |
781 | clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; | 751 | clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; |
782 | clk->set_next_event = arch_timer_set_next_event_phys; | 752 | sne = erratum_handler(set_next_event_phys); |
783 | break; | 753 | break; |
784 | default: | 754 | default: |
785 | BUG(); | 755 | BUG(); |
786 | } | 756 | } |
787 | 757 | ||
788 | arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); | 758 | clk->set_next_event = sne; |
789 | } else { | 759 | } else { |
790 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; | 760 | clk->features |= CLOCK_EVT_FEAT_DYNIRQ; |
791 | clk->name = "arch_mem_timer"; | 761 | clk->name = "arch_mem_timer"; |