Commit | Line | Data |
---|---|---|
f2ae9706 SH |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | |
3 | * Copyright (C) 2020 Arm Limited | |
4 | */ | |
5 | ||
6 | #define pr_fmt(fmt) "smccc: " fmt | |
7 | ||
a37e31fc | 8 | #include <linux/cache.h> |
f2ae9706 SH |
9 | #include <linux/init.h> |
10 | #include <linux/arm-smccc.h> | |
6e085e0a | 11 | #include <linux/kernel.h> |
b83c2d92 | 12 | #include <linux/platform_device.h> |
a37e31fc | 13 | #include <asm/archrandom.h> |
f2ae9706 SH |
14 | |
15 | static u32 smccc_version = ARM_SMCCC_VERSION_1_0; | |
16 | static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE; | |
17 | ||
a37e31fc | 18 | bool __ro_after_init smccc_trng_available = false; |
cfa7ff95 | 19 | u64 __ro_after_init smccc_has_sve_hint = false; |
35727af2 SD |
20 | s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED; |
21 | s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED; | |
a37e31fc | 22 | |
f2ae9706 SH |
23 | void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit) |
24 | { | |
35727af2 SD |
25 | struct arm_smccc_res res; |
26 | ||
f2ae9706 SH |
27 | smccc_version = version; |
28 | smccc_conduit = conduit; | |
a37e31fc AP |
29 | |
30 | smccc_trng_available = smccc_probe_trng(); | |
cfa7ff95 MB |
31 | if (IS_ENABLED(CONFIG_ARM64_SVE) && |
32 | smccc_version >= ARM_SMCCC_VERSION_1_3) | |
33 | smccc_has_sve_hint = true; | |
35727af2 SD |
34 | |
35 | if ((smccc_version >= ARM_SMCCC_VERSION_1_2) && | |
36 | (smccc_conduit != SMCCC_CONDUIT_NONE)) { | |
37 | arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, | |
38 | ARM_SMCCC_ARCH_SOC_ID, &res); | |
39 | if ((s32)res.a0 >= 0) { | |
40 | arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res); | |
41 | smccc_soc_id_version = (s32)res.a0; | |
42 | arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res); | |
43 | smccc_soc_id_revision = (s32)res.a0; | |
44 | } | |
45 | } | |
f2ae9706 SH |
46 | } |
47 | ||
48 | enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void) | |
49 | { | |
50 | if (smccc_version < ARM_SMCCC_VERSION_1_1) | |
51 | return SMCCC_CONDUIT_NONE; | |
52 | ||
53 | return smccc_conduit; | |
54 | } | |
6825f17c | 55 | EXPORT_SYMBOL_GPL(arm_smccc_1_1_get_conduit); |
a4fb1746 SH |
56 | |
57 | u32 arm_smccc_get_version(void) | |
58 | { | |
59 | return smccc_version; | |
60 | } | |
6825f17c | 61 | EXPORT_SYMBOL_GPL(arm_smccc_get_version); |
b83c2d92 | 62 | |
35727af2 SD |
63 | s32 arm_smccc_get_soc_id_version(void) |
64 | { | |
65 | return smccc_soc_id_version; | |
66 | } | |
67 | ||
68 | s32 arm_smccc_get_soc_id_revision(void) | |
69 | { | |
70 | return smccc_soc_id_revision; | |
71 | } | |
9cf3415a | 72 | EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision); |
35727af2 | 73 | |
b83c2d92 AP |
74 | static int __init smccc_devices_init(void) |
75 | { | |
76 | struct platform_device *pdev; | |
77 | ||
78 | if (smccc_trng_available) { | |
79 | pdev = platform_device_register_simple("smccc_trng", -1, | |
80 | NULL, 0); | |
81 | if (IS_ERR(pdev)) | |
82 | pr_err("smccc_trng: could not register device: %ld\n", | |
83 | PTR_ERR(pdev)); | |
84 | } | |
85 | ||
86 | return 0; | |
87 | } | |
88 | device_initcall(smccc_devices_init); |