diff mbox

[2/5] ARM: 7855/1: Add check for Cortex-A15 errata 798181 ECO

Message ID 1383748487-13886-3-git-send-email-paolo.pisati@canonical.com
State New
Headers show

Commit Message

Paolo Pisati Nov. 6, 2013, 2:34 p.m. UTC
From: Rob Herring <rob.herring@calxeda.com>

BugLink: http://bugs.launchpad.net/bugs/1239800

The work-around for A15 errata 798181 is not needed if appropriate ECO
fixes have been applied to r3p2 and earlier core revisions. This can be
checked by reading REVIDR register bits 4 and 9. If only bit 4 is set,
then the IPI broadcast can be skipped.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
(cherry picked from commit 92871b94a5f9892e324c31960678387922c75049 via rmk's
tree http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm.git
for-next)
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 arch/arm/include/asm/cputype.h  |  1 +
 arch/arm/include/asm/tlbflush.h | 48 +++++++++++++++--------------------------
 arch/arm/kernel/setup.c         |  2 ++
 arch/arm/kernel/smp_tlb.c       | 36 +++++++++++++++++++++++++++++--
 4 files changed, 54 insertions(+), 33 deletions(-)

Comments

Andy Whitcroft Nov. 7, 2013, 2:26 p.m. UTC | #1
On Wed, Nov 06, 2013 at 03:34:44PM +0100, Paolo Pisati wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1239800
> 
> The work-around for A15 errata 798181 is not needed if appropriate ECO
> fixes have been applied to r3p2 and earlier core revisions. This can be
> checked by reading REVIDR register bits 4 and 9. If only bit 4 is set,
> then the IPI broadcast can be skipped.
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Reviewed-by: Will Deacon <will.deacon@arm.com>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> (cherry picked from commit 92871b94a5f9892e324c31960678387922c75049 via rmk's
> tree http://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm.git
> for-next)
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---
>  arch/arm/include/asm/cputype.h  |  1 +
>  arch/arm/include/asm/tlbflush.h | 48 +++++++++++++++--------------------------
>  arch/arm/kernel/setup.c         |  2 ++
>  arch/arm/kernel/smp_tlb.c       | 36 +++++++++++++++++++++++++++++--
>  4 files changed, 54 insertions(+), 33 deletions(-)
> 
> diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
> index 9672e97..acdde76 100644
> --- a/arch/arm/include/asm/cputype.h
> +++ b/arch/arm/include/asm/cputype.h
> @@ -10,6 +10,7 @@
>  #define CPUID_TLBTYPE	3
>  #define CPUID_MPUIR	4
>  #define CPUID_MPIDR	5
> +#define CPUID_REVIDR	6
>  
>  #ifdef CONFIG_CPU_V7M
>  #define CPUID_EXT_PFR0	0x40
> diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
> index 3316264..deba3a0 100644
> --- a/arch/arm/include/asm/tlbflush.h
> +++ b/arch/arm/include/asm/tlbflush.h
> @@ -541,37 +541,6 @@ static inline void local_flush_bp_all(void)
>  		isb();
>  }
>  
> -#include <asm/cputype.h>
> -#ifdef CONFIG_ARM_ERRATA_798181
> -static inline int erratum_a15_798181(void)
> -{
> -	unsigned int midr = read_cpuid_id();
> -
> -	/* Cortex-A15 r0p0..r3p2 affected */
> -	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
> -		return 0;
> -	return 1;
> -}
> -
> -static inline void dummy_flush_tlb_a15_erratum(void)
> -{
> -	/*
> -	 * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
> -	 */
> -	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> -	dsb();
> -}
> -#else
> -static inline int erratum_a15_798181(void)
> -{
> -	return 0;
> -}
> -
> -static inline void dummy_flush_tlb_a15_erratum(void)
> -{
> -}
> -#endif
> -
>  /*
>   *	flush_pmd_entry
>   *
> @@ -678,4 +647,21 @@ extern void flush_bp_all(void);
>  
>  #endif
>  
> +#ifndef __ASSEMBLY__
> +#ifdef CONFIG_ARM_ERRATA_798181
> +extern void erratum_a15_798181_init(void);
> +#else
> +static inline void erratum_a15_798181_init(void) {}
> +#endif
> +extern bool (*erratum_a15_798181_handler)(void);
> +
> +static inline bool erratum_a15_798181(void)
> +{
> +	if (unlikely(IS_ENABLED(CONFIG_ARM_ERRATA_798181) &&
> +		erratum_a15_798181_handler))
> +		return erratum_a15_798181_handler();
> +	return false;
> +}
> +#endif
> +
>  #endif
> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
> index afc2489..f3030e3 100644
> --- a/arch/arm/kernel/setup.c
> +++ b/arch/arm/kernel/setup.c
> @@ -599,6 +599,8 @@ static void __init setup_processor(void)
>  	elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
>  #endif
>  
> +	erratum_a15_798181_init();
> +
>  	feat_v6_fixup();
>  
>  	cacheid_init();
> diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
> index 5883b8a..a1c2dc9 100644
> --- a/arch/arm/kernel/smp_tlb.c
> +++ b/arch/arm/kernel/smp_tlb.c
> @@ -70,6 +70,40 @@ static inline void ipi_flush_bp_all(void *ignored)
>  	local_flush_bp_all();
>  }
>  
> +#ifdef CONFIG_ARM_ERRATA_798181
> +bool (*erratum_a15_798181_handler)(void);
> +
> +static bool erratum_a15_798181_partial(void)
> +{
> +	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> +	dsb();
> +	return false;
> +}
> +
> +static bool erratum_a15_798181_broadcast(void)
> +{
> +	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
> +	dsb();
> +	return true;
> +}
> +
> +void erratum_a15_798181_init(void)
> +{
> +	unsigned int midr = read_cpuid_id();
> +	unsigned int revidr = read_cpuid(CPUID_REVIDR);
> +
> +	/* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
> +	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
> +	    (revidr & 0x210) == 0x210) {
> +		return;
> +	}
> +	if (revidr & 0x10)
> +		erratum_a15_798181_handler = erratum_a15_798181_partial;
> +	else
> +		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
> +}
> +#endif
> +
>  static void ipi_flush_tlb_a15_erratum(void *arg)
>  {
>  	dmb();
> @@ -80,7 +114,6 @@ static void broadcast_tlb_a15_erratum(void)
>  	if (!erratum_a15_798181())
>  		return;
>  
> -	dummy_flush_tlb_a15_erratum();
>  	smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1);
>  }
>  
> @@ -92,7 +125,6 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
>  	if (!erratum_a15_798181())
>  		return;
>  
> -	dummy_flush_tlb_a15_erratum();
>  	this_cpu = get_cpu();
>  	a15_erratum_get_cpumask(this_cpu, mm, &mask);
>  	smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);

Looks reasonable.

-apw
diff mbox

Patch

diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 9672e97..acdde76 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -10,6 +10,7 @@ 
 #define CPUID_TLBTYPE	3
 #define CPUID_MPUIR	4
 #define CPUID_MPIDR	5
+#define CPUID_REVIDR	6
 
 #ifdef CONFIG_CPU_V7M
 #define CPUID_EXT_PFR0	0x40
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 3316264..deba3a0 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -541,37 +541,6 @@  static inline void local_flush_bp_all(void)
 		isb();
 }
 
-#include <asm/cputype.h>
-#ifdef CONFIG_ARM_ERRATA_798181
-static inline int erratum_a15_798181(void)
-{
-	unsigned int midr = read_cpuid_id();
-
-	/* Cortex-A15 r0p0..r3p2 affected */
-	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
-		return 0;
-	return 1;
-}
-
-static inline void dummy_flush_tlb_a15_erratum(void)
-{
-	/*
-	 * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
-	 */
-	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
-	dsb();
-}
-#else
-static inline int erratum_a15_798181(void)
-{
-	return 0;
-}
-
-static inline void dummy_flush_tlb_a15_erratum(void)
-{
-}
-#endif
-
 /*
  *	flush_pmd_entry
  *
@@ -678,4 +647,21 @@  extern void flush_bp_all(void);
 
 #endif
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_ARM_ERRATA_798181
+extern void erratum_a15_798181_init(void);
+#else
+static inline void erratum_a15_798181_init(void) {}
+#endif
+extern bool (*erratum_a15_798181_handler)(void);
+
+static inline bool erratum_a15_798181(void)
+{
+	if (unlikely(IS_ENABLED(CONFIG_ARM_ERRATA_798181) &&
+		erratum_a15_798181_handler))
+		return erratum_a15_798181_handler();
+	return false;
+}
+#endif
+
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index afc2489..f3030e3 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -599,6 +599,8 @@  static void __init setup_processor(void)
 	elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
 #endif
 
+	erratum_a15_798181_init();
+
 	feat_v6_fixup();
 
 	cacheid_init();
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 5883b8a..a1c2dc9 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -70,6 +70,40 @@  static inline void ipi_flush_bp_all(void *ignored)
 	local_flush_bp_all();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+bool (*erratum_a15_798181_handler)(void);
+
+static bool erratum_a15_798181_partial(void)
+{
+	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+	dsb();
+	return false;
+}
+
+static bool erratum_a15_798181_broadcast(void)
+{
+	asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+	dsb();
+	return true;
+}
+
+void erratum_a15_798181_init(void)
+{
+	unsigned int midr = read_cpuid_id();
+	unsigned int revidr = read_cpuid(CPUID_REVIDR);
+
+	/* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
+	if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
+	    (revidr & 0x210) == 0x210) {
+		return;
+	}
+	if (revidr & 0x10)
+		erratum_a15_798181_handler = erratum_a15_798181_partial;
+	else
+		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+}
+#endif
+
 static void ipi_flush_tlb_a15_erratum(void *arg)
 {
 	dmb();
@@ -80,7 +114,6 @@  static void broadcast_tlb_a15_erratum(void)
 	if (!erratum_a15_798181())
 		return;
 
-	dummy_flush_tlb_a15_erratum();
 	smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1);
 }
 
@@ -92,7 +125,6 @@  static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
 	if (!erratum_a15_798181())
 		return;
 
-	dummy_flush_tlb_a15_erratum();
 	this_cpu = get_cpu();
 	a15_erratum_get_cpumask(this_cpu, mm, &mask);
 	smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);