brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · 731e6d5 Raw
121 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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");121