File Index
Files and directories
Sign in
FILE

qcom_qseecom.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/qcom/qcom_qseecom.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
  4 * Responsible for setting up and managing QSEECOM client devices.
  5 *
  6 * Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
  7 */
  8#include <linux/auxiliary_bus.h>
  9#include <linux/module.h>
 10#include <linux/platform_device.h>
 11#include <linux/slab.h>
 12#include <linux/types.h>
 13
 14#include <linux/firmware/qcom/qcom_qseecom.h>
 15#include <linux/firmware/qcom/qcom_scm.h>
 16
 17struct qseecom_app_desc {
 18	const char *app_name;
 19	const char *dev_name;
 20};
 21
 22static void qseecom_client_release(struct device *dev)
 23{
 24	struct qseecom_client *client;
 25
 26	client = container_of(dev, struct qseecom_client, aux_dev.dev);
 27	kfree(client);
 28}
 29
 30static void qseecom_client_remove(void *data)
 31{
 32	struct qseecom_client *client = data;
 33
 34	auxiliary_device_delete(&client->aux_dev);
 35	auxiliary_device_uninit(&client->aux_dev);
 36}
 37
 38static int qseecom_client_register(struct platform_device *qseecom_dev,
 39				   const struct qseecom_app_desc *desc)
 40{
 41	struct qseecom_client *client;
 42	u32 app_id;
 43	int ret;
 44
 45	/* Try to find the app ID, skip device if not found */
 46	ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
 47	if (ret)
 48		return ret == -ENOENT ? 0 : ret;
 49
 50	dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
 51
 52	/* Allocate and set-up the client device */
 53	client = kzalloc(sizeof(*client), GFP_KERNEL);
 54	if (!client)
 55		return -ENOMEM;
 56
 57	client->aux_dev.name = desc->dev_name;
 58	client->aux_dev.dev.parent = &qseecom_dev->dev;
 59	client->aux_dev.dev.release = qseecom_client_release;
 60	client->app_id = app_id;
 61
 62	ret = auxiliary_device_init(&client->aux_dev);
 63	if (ret) {
 64		kfree(client);
 65		return ret;
 66	}
 67
 68	ret = auxiliary_device_add(&client->aux_dev);
 69	if (ret) {
 70		auxiliary_device_uninit(&client->aux_dev);
 71		return ret;
 72	}
 73
 74	ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
 75	if (ret)
 76		return ret;
 77
 78	return 0;
 79}
 80
 81/*
 82 * List of supported applications. One client device will be created per entry,
 83 * assuming the app has already been loaded (usually by firmware bootloaders)
 84 * and its ID can be queried successfully.
 85 */
 86static const struct qseecom_app_desc qcom_qseecom_apps[] = {
 87	{ "qcom.tz.uefisecapp", "uefisecapp" },
 88};
 89
 90static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
 91{
 92	int ret;
 93	int i;
 94
 95	/* Set up client devices for each base application */
 96	for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
 97		ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
 98		if (ret)
 99			return ret;
100	}
101
102	return 0;
103}
104
105static struct platform_driver qcom_qseecom_driver = {
106	.driver = {
107		.name	= "qcom_qseecom",
108	},
109	.probe = qcom_qseecom_probe,
110};
111
112static int __init qcom_qseecom_init(void)
113{
114	return platform_driver_register(&qcom_qseecom_driver);
115}
116subsys_initcall(qcom_qseecom_init);
117
118MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
119MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
120MODULE_LICENSE("GPL");
~/ Read-only file preview.