aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c46
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
619static bool arch_timer_this_cpu_has_cntvct_wa(void) 601static 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,
721static int arch_timer_set_next_event_virt(unsigned long evt, 697static 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,
733static int arch_timer_set_next_event_phys(unsigned long evt, 704static 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";