Commit 714be77e authored by Sudeep Holla's avatar Sudeep Holla
Browse files

firmware: arm_ffa: Add support for SMCCC as transport to FFA driver

There are requests to keep the transport separate in order to allow
other possible transports like virtio. So let us keep the SMCCC transport
specific routines abstracted.

It is kept simple for now. Once we add another transport, we can develop
better abstraction.

Link: https://lore.kernel.org/r/20210521151033.181846-4-sudeep.holla@arm.com


Tested-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
Signed-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 3bbfe987
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -14,3 +14,8 @@ config ARM_FFA_TRANSPORT

	  This driver provides interface for all the client drivers making
	  use of the features offered by ARM FF-A.

config ARM_FFA_SMCCC
	bool
	default ARM_FFA_TRANSPORT
	depends on ARM64 && HAVE_ARM_SMCCC_DISCOVERY
+2 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
ffa-bus-y = bus.o
ffa-driver-y = driver.o
ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y)
ffa-transport-$(CONFIG_ARM_FFA_SMCCC) += smccc.o
ffa-module-objs := $(ffa-bus-y) $(ffa-driver-y) $(ffa-transport-y)
obj-$(CONFIG_ARM_FFA_TRANSPORT) = ffa-module.o
+4 −0
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@ typedef void (ffa_fn)(ffa_value_t, ffa_value_t *);
int arm_ffa_bus_init(void);
void arm_ffa_bus_exit(void);

#ifdef CONFIG_ARM_FFA_SMCCC
int __init ffa_transport_init(ffa_fn **invoke_ffa_fn);
#else
static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
{
	return -EOPNOTSUPP;
}
#endif

#endif /* _FFA_COMMON_H */
+39 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2021 ARM Ltd.
 */

#include <linux/printk.h>

#include "common.h"

static void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
{
	arm_smccc_1_2_smc(&args, res);
}

static void __arm_ffa_fn_hvc(ffa_value_t args, ffa_value_t *res)
{
	arm_smccc_1_2_hvc(&args, res);
}

int __init ffa_transport_init(ffa_fn **invoke_ffa_fn)
{
	enum arm_smccc_conduit conduit;

	if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
		return -EOPNOTSUPP;

	conduit = arm_smccc_1_1_get_conduit();
	if (conduit == SMCCC_CONDUIT_NONE) {
		pr_err("%s: invalid SMCCC conduit\n", __func__);
		return -EOPNOTSUPP;
	}

	if (conduit == SMCCC_CONDUIT_SMC)
		*invoke_ffa_fn = __arm_ffa_fn_smc;
	else
		*invoke_ffa_fn = __arm_ffa_fn_hvc;

	return 0;
}