Merge remote-tracking branch 'asoc/fix/dapm' into asoc-linus
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / cpu_errata.c
1 /*
2  * Contains CPU specific errata definitions
3  *
4  * Copyright (C) 2014 ARM Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #define pr_fmt(fmt) "alternatives: " fmt
20
21 #include <linux/types.h>
22 #include <asm/cpu.h>
23 #include <asm/cputype.h>
24 #include <asm/cpufeature.h>
25
26 #define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
27 #define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
28
29 /*
30  * Add a struct or another datatype to the union below if you need
31  * different means to detect an affected CPU.
32  */
33 struct arm64_cpu_capabilities {
34         const char *desc;
35         u16 capability;
36         bool (*is_affected)(struct arm64_cpu_capabilities *);
37         union {
38                 struct {
39                         u32 midr_model;
40                         u32 midr_range_min, midr_range_max;
41                 };
42         };
43 };
44
45 #define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
46                         MIDR_ARCHITECTURE_MASK)
47
48 static bool __maybe_unused
49 is_affected_midr_range(struct arm64_cpu_capabilities *entry)
50 {
51         u32 midr = read_cpuid_id();
52
53         if ((midr & CPU_MODEL_MASK) != entry->midr_model)
54                 return false;
55
56         midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
57
58         return (midr >= entry->midr_range_min && midr <= entry->midr_range_max);
59 }
60
61 #define MIDR_RANGE(model, min, max) \
62         .is_affected = is_affected_midr_range, \
63         .midr_model = model, \
64         .midr_range_min = min, \
65         .midr_range_max = max
66
67 struct arm64_cpu_capabilities arm64_errata[] = {
68 #if     defined(CONFIG_ARM64_ERRATUM_826319) || \
69         defined(CONFIG_ARM64_ERRATUM_827319) || \
70         defined(CONFIG_ARM64_ERRATUM_824069)
71         {
72         /* Cortex-A53 r0p[012] */
73                 .desc = "ARM errata 826319, 827319, 824069",
74                 .capability = ARM64_WORKAROUND_CLEAN_CACHE,
75                 MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
76         },
77 #endif
78 #ifdef CONFIG_ARM64_ERRATUM_819472
79         {
80         /* Cortex-A53 r0p[01] */
81                 .desc = "ARM errata 819472",
82                 .capability = ARM64_WORKAROUND_CLEAN_CACHE,
83                 MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
84         },
85 #endif
86 #ifdef CONFIG_ARM64_ERRATUM_832075
87         {
88         /* Cortex-A57 r0p0 - r1p2 */
89                 .desc = "ARM erratum 832075",
90                 .capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
91                 MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12),
92         },
93 #endif
94         {
95         }
96 };
97
98 void check_local_cpu_errata(void)
99 {
100         struct arm64_cpu_capabilities *cpus = arm64_errata;
101         int i;
102
103         for (i = 0; cpus[i].desc; i++) {
104                 if (!cpus[i].is_affected(&cpus[i]))
105                         continue;
106
107                 if (!cpus_have_cap(cpus[i].capability))
108                         pr_info("enabling workaround for %s\n", cpus[i].desc);
109                 cpus_set_cap(cpus[i].capability);
110         }
111 }