diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/arm-smccc.h | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 67f6fdf2e7cd..eb7eab04755a 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -639,5 +639,45 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, method; \ }) +#ifdef CONFIG_ARM64 + +#define __fail_smccc_1_2(___res) \ + do { \ + if (___res) \ + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ + } while (0) + +/* + * arm_smccc_1_2_invoke() - make an SMCCC v1.2 compliant call + * + * @args: SMC args are in the a0..a17 fields of the arm_smcc_1_2_regs structure + * @res: result values from registers 0 to 17 + * + * This macro will make either an HVC call or an SMC call depending on the + * current SMCCC conduit. If no valid conduit is available then -1 + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). + * + * The return value also provides the conduit that was used. + */ +#define arm_smccc_1_2_invoke(args, res) ({ \ + struct arm_smccc_1_2_regs *__args = args; \ + struct arm_smccc_1_2_regs *__res = res; \ + int method = arm_smccc_1_1_get_conduit(); \ + switch (method) { \ + case SMCCC_CONDUIT_HVC: \ + arm_smccc_1_2_hvc(__args, __res); \ + break; \ + case SMCCC_CONDUIT_SMC: \ + arm_smccc_1_2_smc(__args, __res); \ + break; \ + default: \ + __fail_smccc_1_2(__res); \ + method = SMCCC_CONDUIT_NONE; \ + break; \ + } \ + method; \ + }) +#endif /*CONFIG_ARM64*/ + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ |
