Commit | Line | Data |
---|---|---|
df857416 MR |
1 | /* |
2 | * Record and handle CPU attributes. | |
3 | * | |
4 | * Copyright (C) 2014 ARM Ltd. | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | #include <asm/arch_timer.h> | |
18 | #include <asm/cachetype.h> | |
19 | #include <asm/cpu.h> | |
20 | #include <asm/cputype.h> | |
21 | ||
59ccc0d4 | 22 | #include <linux/bitops.h> |
df857416 | 23 | #include <linux/init.h> |
59ccc0d4 | 24 | #include <linux/printk.h> |
df857416 MR |
25 | #include <linux/smp.h> |
26 | ||
27 | /* | |
28 | * In case the boot CPU is hotpluggable, we record its initial state and | |
29 | * current state separately. Certain system registers may contain different | |
30 | * values depending on configuration at or after reset. | |
31 | */ | |
32 | DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); | |
33 | static struct cpuinfo_arm64 boot_cpu_data; | |
34 | ||
59ccc0d4 MR |
35 | static char *icache_policy_str[] = { |
36 | [ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN", | |
37 | [ICACHE_POLICY_AIVIVT] = "AIVIVT", | |
38 | [ICACHE_POLICY_VIPT] = "VIPT", | |
39 | [ICACHE_POLICY_PIPT] = "PIPT", | |
40 | }; | |
41 | ||
42 | unsigned long __icache_flags; | |
43 | ||
44 | static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info) | |
45 | { | |
46 | unsigned int cpu = smp_processor_id(); | |
47 | u32 l1ip = CTR_L1IP(info->reg_ctr); | |
48 | ||
49 | if (l1ip != ICACHE_POLICY_PIPT) | |
50 | set_bit(ICACHEF_ALIASING, &__icache_flags); | |
51 | if (l1ip == ICACHE_POLICY_AIVIVT); | |
52 | set_bit(ICACHEF_AIVIVT, &__icache_flags); | |
53 | ||
54 | pr_info("Detected %s I-cache on CPU%d", icache_policy_str[l1ip], cpu); | |
55 | } | |
56 | ||
df857416 MR |
57 | static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) |
58 | { | |
59 | info->reg_cntfrq = arch_timer_get_cntfrq(); | |
60 | info->reg_ctr = read_cpuid_cachetype(); | |
61 | info->reg_dczid = read_cpuid(DCZID_EL0); | |
62 | info->reg_midr = read_cpuid_id(); | |
63 | ||
64 | info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1); | |
65 | info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1); | |
66 | info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); | |
67 | info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); | |
68 | info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1); | |
69 | info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1); | |
70 | ||
71 | info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1); | |
72 | info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1); | |
73 | info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1); | |
74 | info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1); | |
75 | info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1); | |
76 | info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1); | |
77 | info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1); | |
78 | info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1); | |
79 | info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1); | |
80 | info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1); | |
81 | info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1); | |
82 | info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1); | |
59ccc0d4 MR |
83 | |
84 | cpuinfo_detect_icache_policy(info); | |
df857416 MR |
85 | } |
86 | ||
87 | void cpuinfo_store_cpu(void) | |
88 | { | |
89 | struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data); | |
90 | __cpuinfo_store_cpu(info); | |
91 | } | |
92 | ||
93 | void __init cpuinfo_store_boot_cpu(void) | |
94 | { | |
95 | struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0); | |
96 | __cpuinfo_store_cpu(info); | |
97 | ||
98 | boot_cpu_data = *info; | |
99 | } |