162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2022, Microchip
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/arm-smccc.h>
762306a36Sopenharmony_ci#include <linux/of.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "sam_secure.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic bool optee_available;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define SAM_SIP_SMC_STD_CALL_VAL(func_num) \
1462306a36Sopenharmony_ci	ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
1562306a36Sopenharmony_ci	ARM_SMCCC_OWNER_SIP, (func_num))
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct arm_smccc_res sam_smccc_call(u32 fn, u32 arg0, u32 arg1)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	struct arm_smccc_res res = {.a0 = -1};
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (WARN_ON(!optee_available))
2262306a36Sopenharmony_ci		return res;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	arm_smccc_smc(SAM_SIP_SMC_STD_CALL_VAL(fn), arg0, arg1, 0, 0, 0, 0, 0,
2562306a36Sopenharmony_ci		      &res);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	return res;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cibool sam_linux_is_optee_available(void)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	/* If optee has been detected, then we are running in normal world */
3362306a36Sopenharmony_ci	return optee_available;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_civoid __init sam_secure_init(void)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	struct device_node *np;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	/*
4162306a36Sopenharmony_ci	 * We only check that the OP-TEE node is present and available. The
4262306a36Sopenharmony_ci	 * OP-TEE kernel driver is not needed for the type of interaction made
4362306a36Sopenharmony_ci	 * with OP-TEE here so the driver's status is not checked.
4462306a36Sopenharmony_ci	 */
4562306a36Sopenharmony_ci	np = of_find_node_by_path("/firmware/optee");
4662306a36Sopenharmony_ci	if (np && of_device_is_available(np))
4762306a36Sopenharmony_ci		optee_available = true;
4862306a36Sopenharmony_ci	of_node_put(np);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (optee_available)
5162306a36Sopenharmony_ci		pr_info("Running under OP-TEE firmware\n");
5262306a36Sopenharmony_ci}
53