Commit | Line | Data |
---|---|---|
caab277b | 1 | // SPDX-License-Identifier: GPL-2.0-only |
e2c0cdfb PD |
2 | /* |
3 | * Copied from arch/arm64/kernel/cpufeature.c | |
4 | * | |
5 | * Copyright (C) 2015 ARM Ltd. | |
6 | * Copyright (C) 2017 SiFive | |
e2c0cdfb PD |
7 | */ |
8 | ||
9 | #include <linux/of.h> | |
10 | #include <asm/processor.h> | |
11 | #include <asm/hwcap.h> | |
fbdc6193 | 12 | #include <asm/smp.h> |
e2c0cdfb PD |
13 | |
14 | unsigned long elf_hwcap __read_mostly; | |
9411ec60 AK |
15 | #ifdef CONFIG_FPU |
16 | bool has_fpu __read_mostly; | |
17 | #endif | |
e2c0cdfb PD |
18 | |
19 | void riscv_fill_hwcap(void) | |
20 | { | |
dd81c8ab | 21 | struct device_node *node; |
e2c0cdfb PD |
22 | const char *isa; |
23 | size_t i; | |
24 | static unsigned long isa2hwcap[256] = {0}; | |
25 | ||
26 | isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I; | |
27 | isa2hwcap['m'] = isa2hwcap['M'] = COMPAT_HWCAP_ISA_M; | |
28 | isa2hwcap['a'] = isa2hwcap['A'] = COMPAT_HWCAP_ISA_A; | |
29 | isa2hwcap['f'] = isa2hwcap['F'] = COMPAT_HWCAP_ISA_F; | |
30 | isa2hwcap['d'] = isa2hwcap['D'] = COMPAT_HWCAP_ISA_D; | |
31 | isa2hwcap['c'] = isa2hwcap['C'] = COMPAT_HWCAP_ISA_C; | |
32 | ||
33 | elf_hwcap = 0; | |
34 | ||
dd81c8ab | 35 | for_each_of_cpu_node(node) { |
fbdc6193 | 36 | unsigned long this_hwcap = 0; |
e2c0cdfb | 37 | |
fbdc6193 AP |
38 | if (riscv_of_processor_hartid(node) < 0) |
39 | continue; | |
e2c0cdfb | 40 | |
fbdc6193 AP |
41 | if (of_property_read_string(node, "riscv,isa", &isa)) { |
42 | pr_warn("Unable to find \"riscv,isa\" devicetree entry\n"); | |
43 | continue; | |
44 | } | |
45 | ||
46 | for (i = 0; i < strlen(isa); ++i) | |
47 | this_hwcap |= isa2hwcap[(unsigned char)(isa[i])]; | |
48 | ||
49 | /* | |
50 | * All "okay" hart should have same isa. Set HWCAP based on | |
51 | * common capabilities of every "okay" hart, in case they don't | |
52 | * have. | |
53 | */ | |
54 | if (elf_hwcap) | |
55 | elf_hwcap &= this_hwcap; | |
56 | else | |
57 | elf_hwcap = this_hwcap; | |
58 | } | |
e2c0cdfb | 59 | |
86e581e3 PD |
60 | /* We don't support systems with F but without D, so mask those out |
61 | * here. */ | |
62 | if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & COMPAT_HWCAP_ISA_D)) { | |
7265d103 | 63 | pr_info("This kernel does not support systems with F but not D\n"); |
86e581e3 PD |
64 | elf_hwcap &= ~COMPAT_HWCAP_ISA_F; |
65 | } | |
66 | ||
7265d103 | 67 | pr_info("elf_hwcap is 0x%lx\n", elf_hwcap); |
9411ec60 AK |
68 | |
69 | #ifdef CONFIG_FPU | |
70 | if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)) | |
71 | has_fpu = true; | |
72 | #endif | |
e2c0cdfb | 73 | } |