aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2013-10-09 12:26:44 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-10-29 07:06:13 -0400
commit92871b94a5f9892e324c31960678387922c75049 (patch)
tree8c47f2a0af3c2d21c71eeba12c843fb0eb7a4795
parent0cbad9c9dfe0c38e8ec7385b39087c005a6dee3e (diff)
ARM: 7855/1: Add check for Cortex-A15 errata 798181 ECO
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>
-rw-r--r--arch/arm/include/asm/cputype.h1
-rw-r--r--arch/arm/include/asm/tlbflush.h48
-rw-r--r--arch/arm/kernel/setup.c2
-rw-r--r--arch/arm/kernel/smp_tlb.c36
4 files changed, 54 insertions, 33 deletions
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 9672e978d50d..acdde76b39bb 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -10,6 +10,7 @@
10#define CPUID_TLBTYPE 3 10#define CPUID_TLBTYPE 3
11#define CPUID_MPUIR 4 11#define CPUID_MPUIR 4
12#define CPUID_MPIDR 5 12#define CPUID_MPIDR 5
13#define CPUID_REVIDR 6
13 14
14#ifdef CONFIG_CPU_V7M 15#ifdef CONFIG_CPU_V7M
15#define CPUID_EXT_PFR0 0x40 16#define CPUID_EXT_PFR0 0x40
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 38960264040c..def9e570199f 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -560,37 +560,6 @@ static inline void __flush_bp_all(void)
560 asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero)); 560 asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero));
561} 561}
562 562
563#include <asm/cputype.h>
564#ifdef CONFIG_ARM_ERRATA_798181
565static inline int erratum_a15_798181(void)
566{
567 unsigned int midr = read_cpuid_id();
568
569 /* Cortex-A15 r0p0..r3p2 affected */
570 if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
571 return 0;
572 return 1;
573}
574
575static inline void dummy_flush_tlb_a15_erratum(void)
576{
577 /*
578 * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
579 */
580 asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
581 dsb(ish);
582}
583#else
584static inline int erratum_a15_798181(void)
585{
586 return 0;
587}
588
589static inline void dummy_flush_tlb_a15_erratum(void)
590{
591}
592#endif
593
594/* 563/*
595 * flush_pmd_entry 564 * flush_pmd_entry
596 * 565 *
@@ -697,4 +666,21 @@ extern void flush_bp_all(void);
697 666
698#endif 667#endif
699 668
669#ifndef __ASSEMBLY__
670#ifdef CONFIG_ARM_ERRATA_798181
671extern void erratum_a15_798181_init(void);
672#else
673static inline void erratum_a15_798181_init(void) {}
674#endif
675extern bool (*erratum_a15_798181_handler)(void);
676
677static inline bool erratum_a15_798181(void)
678{
679 if (unlikely(IS_ENABLED(CONFIG_ARM_ERRATA_798181) &&
680 erratum_a15_798181_handler))
681 return erratum_a15_798181_handler();
682 return false;
683}
684#endif
685
700#endif 686#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 0e1e2b3afa45..a4852dea088b 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -599,6 +599,8 @@ static void __init setup_processor(void)
599 elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT); 599 elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
600#endif 600#endif
601 601
602 erratum_a15_798181_init();
603
602 feat_v6_fixup(); 604 feat_v6_fixup();
603 605
604 cacheid_init(); 606 cacheid_init();
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 83ccca303df8..95d063620b76 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)
70 local_flush_bp_all(); 70 local_flush_bp_all();
71} 71}
72 72
73#ifdef CONFIG_ARM_ERRATA_798181
74bool (*erratum_a15_798181_handler)(void);
75
76static bool erratum_a15_798181_partial(void)
77{
78 asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
79 dsb(ish);
80 return false;
81}
82
83static bool erratum_a15_798181_broadcast(void)
84{
85 asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
86 dsb(ish);
87 return true;
88}
89
90void erratum_a15_798181_init(void)
91{
92 unsigned int midr = read_cpuid_id();
93 unsigned int revidr = read_cpuid(CPUID_REVIDR);
94
95 /* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
96 if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
97 (revidr & 0x210) == 0x210) {
98 return;
99 }
100 if (revidr & 0x10)
101 erratum_a15_798181_handler = erratum_a15_798181_partial;
102 else
103 erratum_a15_798181_handler = erratum_a15_798181_broadcast;
104}
105#endif
106
73static void ipi_flush_tlb_a15_erratum(void *arg) 107static void ipi_flush_tlb_a15_erratum(void *arg)
74{ 108{
75 dmb(); 109 dmb();
@@ -80,7 +114,6 @@ static void broadcast_tlb_a15_erratum(void)
80 if (!erratum_a15_798181()) 114 if (!erratum_a15_798181())
81 return; 115 return;
82 116
83 dummy_flush_tlb_a15_erratum();
84 smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1); 117 smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1);
85} 118}
86 119
@@ -92,7 +125,6 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
92 if (!erratum_a15_798181()) 125 if (!erratum_a15_798181())
93 return; 126 return;
94 127
95 dummy_flush_tlb_a15_erratum();
96 this_cpu = get_cpu(); 128 this_cpu = get_cpu();
97 a15_erratum_get_cpumask(this_cpu, mm, &mask); 129 a15_erratum_get_cpumask(this_cpu, mm, &mask);
98 smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1); 130 smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);