Model OP-TEE as a platform device/driver
-----BEGIN PGP SIGNATURE----- iQJOBAABCgA4FiEEcK3MsDvGvFp6zV9ztbC4QZeP7NMFAl4O+/YaHGplbnMud2lr bGFuZGVyQGxpbmFyby5vcmcACgkQtbC4QZeP7NMFTg/+LxPl+Kj5+mjJaHfxDoIB JtRwwQx0rA1GEI+LYPUE/1DuDFRv9osKDXGLQtk9iDCn9Zyn1UI5Qqmbqsaw8ocl tCdFE+4izHkWqnn+bxhhIpbtfj0pY6n9v7xSoqR48cmKZc5eIm/5Vdmgl4Az2Jml 2GyupjkdX+eXpK2da0pGwL46t+ExjzkoQvKp4YSR6Lcv+IcRQ1mbEMZNki9iUxQU 6o73gia+1rAApc/ByIuDmXhN4H8vvlEwXw4Kcdk/KZuuyDXRAOsTz5kd/hnQwM8a IGZMel6qNfo7eJS1juVblXyD8KDoGm7/WtXzVsTYrqfdKpwMlRwjOS6axI7nufDL OXRmTvrcGJsBIWvBvf/rnGeDsAscpqEdQ8qlFw0t3q/A5EfTQshERc37D3jwRqUg RAN99F3wpHVgswePoO2fk8LEcG8Xs2YnMrJcNnigIyFFVtrmSKvc5oBtuDjc55x3 RMAYaWHkKHPvOkdV7O+ZMYkUh/pLI3wTeqqTdOTtzyZ3ywzUXPdJI0d6EUS9RRtJ igv5dGjDUwF3tEA704p5Jg4t1kajxsudkOGXF0irRJ8ObQs5w4qlHnohbYWCAQ2N ZPYROo90lZiJzZd7AZscqKZf76+f80T5eDE67N4PAQFSrD7G/OTp+fDC8WpLzTrG QmYLD+QCuTwaHZ6O/MKdctI= =8BSE -----END PGP SIGNATURE----- Merge tag 'tee-optee-pldrv-for-5.6' of git://git.linaro.org:/people/jens.wiklander/linux-tee into arm/drivers Model OP-TEE as a platform device/driver * tag 'tee-optee-pldrv-for-5.6' of git://git.linaro.org:/people/jens.wiklander/linux-tee: optee: model OP-TEE as a platform device/driver Link: https://lore.kernel.org/r/20200103090025.GA11243@jax Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
bcbf053102
@ -534,13 +534,13 @@ 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)
|
||||
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);
|
||||
}
|
||||
@ -554,7 +554,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 = ERR_PTR(-EINVAL);
|
||||
@ -564,25 +594,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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -598,7 +628,7 @@ static struct optee *optee_probe(struct device_node *np)
|
||||
pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
|
||||
|
||||
if (IS_ERR(pool))
|
||||
return (void *)pool;
|
||||
return PTR_ERR(pool);
|
||||
|
||||
optee = kzalloc(sizeof(*optee), GFP_KERNEL);
|
||||
if (!optee) {
|
||||
@ -643,7 +673,16 @@ static struct optee *optee_probe(struct device_node *np)
|
||||
if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
|
||||
pr_info("dynamic shared memory is enabled\n");
|
||||
|
||||
return optee;
|
||||
platform_set_drvdata(pdev, optee);
|
||||
|
||||
rc = optee_enumerate_devices();
|
||||
if (rc) {
|
||||
optee_remove(pdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_info("initialized driver\n");
|
||||
return 0;
|
||||
err:
|
||||
if (optee) {
|
||||
/*
|
||||
@ -659,92 +698,28 @@ err:
|
||||
tee_shm_pool_free(pool);
|
||||
if (memremaped_shm)
|
||||
memunmap(memremaped_shm);
|
||||
return ERR_PTR(rc);
|
||||
return 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);
|
||||
}
|
||||
|
||||
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 = NULL;
|
||||
struct device_node *np = NULL;
|
||||
struct optee *optee = NULL;
|
||||
int rc = 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
rc = optee_enumerate_devices();
|
||||
if (rc) {
|
||||
optee_remove(optee);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_info("initialized driver\n");
|
||||
|
||||
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);
|
||||
static struct platform_driver optee_driver = {
|
||||
.probe = optee_probe,
|
||||
.remove = optee_remove,
|
||||
.driver = {
|
||||
.name = "optee",
|
||||
.of_match_table = optee_dt_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");
|
||||
|
Loading…
Reference in New Issue
Block a user