Loading arch/arm/include/asm/arch_timer.h +29 −2 Original line number Diff line number Diff line Loading @@ -11,6 +11,20 @@ #include <clocksource/arm_arch_timer.h> #ifdef CONFIG_ARM_ARCH_TIMER #ifdef CONFIG_ARM_ERRATUM_858921 DECLARE_PER_CPU(bool, timer_erratum_858921_workaround_enabled); static __always_inline bool erratum_858921_workaround_enabled(void) { return this_cpu_read(timer_erratum_858921_workaround_enabled); } #else static __always_inline bool erratum_858921_workaround_enabled(void) { return false; } #endif int arch_timer_arch_init(void); /* Loading Loading @@ -79,12 +93,19 @@ static inline u32 arch_timer_get_cntfrq(void) return val; } #define L32_BITS 0x00000000FFFFFFFF static inline u64 arch_counter_get_cntpct(void) { u64 cval; isb(); if (erratum_858921_workaround_enabled()) { do { asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r"(cval)); } while ((cval & L32_BITS) == L32_BITS); } else { asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); } return cval; } Loading @@ -93,7 +114,13 @@ static inline u64 arch_counter_get_cntvct(void) u64 cval; isb(); if (erratum_858921_workaround_enabled()) { do { asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r"(cval)); } while ((cval & L32_BITS) == L32_BITS); } else { asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); } return cval; } Loading arch/arm/include/asm/cputype.h +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ #define ARM_CPU_PART_CORTEX_A72 0x4100d080 #define ARM_CPU_PART_CORTEX_A73 0x4100d090 #define ARM_CPU_PART_CORTEX_A75 0x4100d0a0 #define QCOM_CPU_PART_KRYO2XX_GOLD 0x51008000 #define ARM_CPU_PART_MASK 0xff00fff0 /* Broadcom implemented processors */ Loading drivers/clocksource/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -366,6 +366,16 @@ config ARM64_ERRATUM_858921 The workaround will be dynamically enabled when an affected core is detected. config ARM_ERRATUM_858921 bool "Workaround for Cortex-A73(AArch32) erratum 858921" default y depends on ARM_ARCH_TIMER && ARM help This option enables a workaround applicable to AArch32 Cortex-A73 (all versions), whose counter may return incorrect values. The workaround will be dynamically enabled when an affected core is detected. config SUN50I_ERRATUM_UNKNOWN1 bool "Workaround for Allwinner A64 erratum UNKNOWN1" default y Loading drivers/clocksource/arm_arch_timer.c +21 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <asm/arch_timer.h> #include <asm/traps.h> #include <asm/virt.h> #include <asm/cputype.h> #include <clocksource/arm_arch_timer.h> Loading Loading @@ -193,6 +194,25 @@ struct ate_acpi_oem_info { u32 oem_revision; }; #ifdef CONFIG_ARM_ERRATUM_858921 DEFINE_PER_CPU(bool, timer_erratum_858921_workaround_enabled); EXPORT_PER_CPU_SYMBOL(timer_erratum_858921_workaround_enabled); static void arch_timer_check_858921_workaround(void) { unsigned int cpuid_part; cpuid_part = read_cpuid_part(); if (cpuid_part == ARM_CPU_PART_CORTEX_A73 || cpuid_part == QCOM_CPU_PART_KRYO2XX_GOLD) { this_cpu_write(timer_erratum_858921_workaround_enabled, true); } else { this_cpu_write(timer_erratum_858921_workaround_enabled, false); } } #else #define arch_timer_check_858921_workaround() do { } while (0) #endif #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number Loading Loading @@ -803,6 +823,7 @@ static void __arch_timer_setup(unsigned type, } arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); arch_timer_check_858921_workaround(); } else { clk->features |= CLOCK_EVT_FEAT_DYNIRQ; clk->name = "arch_mem_timer"; Loading Loading
arch/arm/include/asm/arch_timer.h +29 −2 Original line number Diff line number Diff line Loading @@ -11,6 +11,20 @@ #include <clocksource/arm_arch_timer.h> #ifdef CONFIG_ARM_ARCH_TIMER #ifdef CONFIG_ARM_ERRATUM_858921 DECLARE_PER_CPU(bool, timer_erratum_858921_workaround_enabled); static __always_inline bool erratum_858921_workaround_enabled(void) { return this_cpu_read(timer_erratum_858921_workaround_enabled); } #else static __always_inline bool erratum_858921_workaround_enabled(void) { return false; } #endif int arch_timer_arch_init(void); /* Loading Loading @@ -79,12 +93,19 @@ static inline u32 arch_timer_get_cntfrq(void) return val; } #define L32_BITS 0x00000000FFFFFFFF static inline u64 arch_counter_get_cntpct(void) { u64 cval; isb(); if (erratum_858921_workaround_enabled()) { do { asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r"(cval)); } while ((cval & L32_BITS) == L32_BITS); } else { asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); } return cval; } Loading @@ -93,7 +114,13 @@ static inline u64 arch_counter_get_cntvct(void) u64 cval; isb(); if (erratum_858921_workaround_enabled()) { do { asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r"(cval)); } while ((cval & L32_BITS) == L32_BITS); } else { asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); } return cval; } Loading
arch/arm/include/asm/cputype.h +1 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ #define ARM_CPU_PART_CORTEX_A72 0x4100d080 #define ARM_CPU_PART_CORTEX_A73 0x4100d090 #define ARM_CPU_PART_CORTEX_A75 0x4100d0a0 #define QCOM_CPU_PART_KRYO2XX_GOLD 0x51008000 #define ARM_CPU_PART_MASK 0xff00fff0 /* Broadcom implemented processors */ Loading
drivers/clocksource/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -366,6 +366,16 @@ config ARM64_ERRATUM_858921 The workaround will be dynamically enabled when an affected core is detected. config ARM_ERRATUM_858921 bool "Workaround for Cortex-A73(AArch32) erratum 858921" default y depends on ARM_ARCH_TIMER && ARM help This option enables a workaround applicable to AArch32 Cortex-A73 (all versions), whose counter may return incorrect values. The workaround will be dynamically enabled when an affected core is detected. config SUN50I_ERRATUM_UNKNOWN1 bool "Workaround for Allwinner A64 erratum UNKNOWN1" default y Loading
drivers/clocksource/arm_arch_timer.c +21 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <asm/arch_timer.h> #include <asm/traps.h> #include <asm/virt.h> #include <asm/cputype.h> #include <clocksource/arm_arch_timer.h> Loading Loading @@ -193,6 +194,25 @@ struct ate_acpi_oem_info { u32 oem_revision; }; #ifdef CONFIG_ARM_ERRATUM_858921 DEFINE_PER_CPU(bool, timer_erratum_858921_workaround_enabled); EXPORT_PER_CPU_SYMBOL(timer_erratum_858921_workaround_enabled); static void arch_timer_check_858921_workaround(void) { unsigned int cpuid_part; cpuid_part = read_cpuid_part(); if (cpuid_part == ARM_CPU_PART_CORTEX_A73 || cpuid_part == QCOM_CPU_PART_KRYO2XX_GOLD) { this_cpu_write(timer_erratum_858921_workaround_enabled, true); } else { this_cpu_write(timer_erratum_858921_workaround_enabled, false); } } #else #define arch_timer_check_858921_workaround() do { } while (0) #endif #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number Loading Loading @@ -803,6 +823,7 @@ static void __arch_timer_setup(unsigned type, } arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); arch_timer_check_858921_workaround(); } else { clk->features |= CLOCK_EVT_FEAT_DYNIRQ; clk->name = "arch_mem_timer"; Loading