Unverified Commit 251d793c authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1935 [openEuler-1.0-LTS] Add Phytium optee driver support

Merge Pull Request from: @tian_wei0822 
 
optee driver support for phytium cpus. 
 
Link:https://gitee.com/openeuler/kernel/pulls/1935

 

Reviewed-by: default avatarMao HongBo <maohongbo@phytium.com.cn>
Signed-off-by: default avatarZhang Changzhong <zhangchangzhong@huawei.com>
parents 5854672e 14542039
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -13,3 +13,33 @@ config OPTEE_SHM_NUM_PRIV_PAGES
	help
	  This sets the number of private shared memory pages to be
	  used by OP-TEE TEE driver.

if OPTEE

choice
	prompt "Default conduit method"
	default OPTEE_DEFAULT_METHOD_NONE
	help
	  This option sets the default conduit method for OP-TEE in case
	  firmware misses "method" property. If in doubt, select "none"
	  which depends on firmware to provide the value.

config OPTEE_DEFAULT_METHOD_NONE
	bool "none"
	help
	  There is no default conduit method used by the driver. Require
	  firwmare to provide the method explicitly.

config OPTEE_DEFAULT_METHOD_HVC
	bool "hvc"
	help
	  Use the "hvc" as default conduit method.

config OPTEE_DEFAULT_METHOD_SMC
	bool "smc"
	help
	  Use the "hvc" as default conduit method.

endchoice

endif
+75 −80
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/acpi.h>
#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/io.h>
@@ -529,15 +530,23 @@ static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
	arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
}

static optee_invoke_fn *get_invoke_func(struct device_node *np)
#if defined(CONFIG_OPTEE_DEFAULT_METHOD_HVC)
#define DEFAULT_CONDUIT_METHOD optee_smccc_hvc
#elif defined(CONFIG_OPTEE_DEFAULT_METHOD_SMC)
#define DEFAULT_CONDUIT_METHOD optee_smccc_hvc
#else
#define DEFAULT_CONDUIT_METHOD ERR_PTR(-ENXIO)
#endif

static optee_invoke_fn *get_invoke_func(struct device *dev)
{
	const char *method;

	pr_info("probing for conduit method from DT.\n");
	pr_info("probing for conduit method.\n");

	if (of_property_read_string(np, "method", &method)) {
	if (device_property_read_string(dev, "method", &method)) {
		pr_warn("missing \"method\" property\n");
		return ERR_PTR(-ENXIO);
		return DEFAULT_CONDUIT_METHOD;
	}

	if (!strcmp("hvc", method))
@@ -549,7 +558,37 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np)
	return ERR_PTR(-EINVAL);
}

static struct optee *optee_probe(struct device_node *np)
static int optee_remove(struct platform_device *pdev)
{
	struct optee *optee = platform_get_drvdata(pdev);

	/*
	 * Ask OP-TEE to free all cached shared memory objects to decrease
	 * reference counters and also avoid wild pointers in secure world
	 * into the old shared memory range.
	 */
	optee_disable_shm_cache(optee);

	/*
	 * The two devices have to be unregistered before we can free the
	 * other resources.
	 */
	tee_device_unregister(optee->supp_teedev);
	tee_device_unregister(optee->teedev);

	tee_shm_pool_free(optee->pool);
	if (optee->memremaped_shm)
		memunmap(optee->memremaped_shm);
	optee_wait_queue_exit(&optee->wait_queue);
	optee_supp_uninit(&optee->supp);
	mutex_destroy(&optee->call_queue.mutex);

	kfree(optee);

	return 0;
}

static int optee_probe(struct platform_device *pdev)
{
	optee_invoke_fn *invoke_fn;
	struct tee_shm_pool *pool;
@@ -559,25 +598,25 @@ static struct optee *optee_probe(struct device_node *np)
	u32 sec_caps;
	int rc;

	invoke_fn = get_invoke_func(np);
	invoke_fn = get_invoke_func(&pdev->dev);
	if (IS_ERR(invoke_fn))
		return (void *)invoke_fn;
		return PTR_ERR(invoke_fn);

	if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
		pr_warn("api uid mismatch\n");
		return ERR_PTR(-EINVAL);
		return -EINVAL;
	}

	optee_msg_get_os_revision(invoke_fn);

	if (!optee_msg_api_revision_is_compatible(invoke_fn)) {
		pr_warn("api revision mismatch\n");
		return ERR_PTR(-EINVAL);
		return -EINVAL;
	}

	if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
		pr_warn("capabilities mismatch\n");
		return ERR_PTR(-EINVAL);
		return -EINVAL;
	}

	/*
@@ -589,7 +628,7 @@ static struct optee *optee_probe(struct device_node *np)

	pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps);
	if (IS_ERR(pool))
		return (void *)pool;
		return PTR_ERR(pool);

	optee = kzalloc(sizeof(*optee), GFP_KERNEL);
	if (!optee) {
@@ -631,8 +670,10 @@ static struct optee *optee_probe(struct device_node *np)

	optee_enable_shm_cache(optee);

	platform_set_drvdata(pdev, optee);

	pr_info("initialized driver\n");
	return optee;
	return 0;
err:
	if (optee) {
		/*
@@ -648,83 +689,37 @@ static struct optee *optee_probe(struct device_node *np)
		tee_shm_pool_free(pool);
	if (memremaped_shm)
		memunmap(memremaped_shm);
	return ERR_PTR(rc);
}

static void optee_remove(struct optee *optee)
{
	/*
	 * Ask OP-TEE to free all cached shared memory objects to decrease
	 * reference counters and also avoid wild pointers in secure world
	 * into the old shared memory range.
	 */
	optee_disable_shm_cache(optee);

	/*
	 * The two devices has to be unregistered before we can free the
	 * other resources.
	 */
	tee_device_unregister(optee->supp_teedev);
	tee_device_unregister(optee->teedev);

	tee_shm_pool_free(optee->pool);
	if (optee->memremaped_shm)
		memunmap(optee->memremaped_shm);
	optee_wait_queue_exit(&optee->wait_queue);
	optee_supp_uninit(&optee->supp);
	mutex_destroy(&optee->call_queue.mutex);

	kfree(optee);
	return rc;
}

static const struct of_device_id optee_match[] = {
static const struct of_device_id optee_dt_match[] = {
	{ .compatible = "linaro,optee-tz" },
	{},
};
MODULE_DEVICE_TABLE(of, optee_dt_match);

static struct optee *optee_svc;

static int __init optee_driver_init(void)
{
	struct device_node *fw_np;
	struct device_node *np;
	struct optee *optee;

	/* Node is supposed to be below /firmware */
	fw_np = of_find_node_by_name(NULL, "firmware");
	if (!fw_np)
		return -ENODEV;

	np = of_find_matching_node(fw_np, optee_match);
	if (!np || !of_device_is_available(np)) {
		of_node_put(np);
		return -ENODEV;
	}

	optee = optee_probe(np);
	of_node_put(np);

	if (IS_ERR(optee))
		return PTR_ERR(optee);

	optee_svc = optee;

	return 0;
}
module_init(optee_driver_init);

static void __exit optee_driver_exit(void)
{
	struct optee *optee = optee_svc;

	optee_svc = NULL;
	if (optee)
		optee_remove(optee);
}
module_exit(optee_driver_exit);
#ifdef CONFIG_ACPI
static const struct acpi_device_id optee_acpi_match[] = {
	{ "PHYT8003" },
	{ }
};
MODULE_DEVICE_TABLE(acpi, optee_acpi_match);
#endif

static struct platform_driver optee_driver = {
	.probe  = optee_probe,
	.remove = optee_remove,
	.driver = {
		.name = "optee",
		.of_match_table = optee_dt_match,
		.acpi_match_table = ACPI_PTR(optee_acpi_match),
	},
};
module_platform_driver(optee_driver);

MODULE_AUTHOR("Linaro");
MODULE_DESCRIPTION("OP-TEE driver");
MODULE_SUPPORTED_DEVICE("");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:optee");