bdac188ec3
We're getting more and more qcom specific .c files in drivers/firmware/ and about to get even more. Create a separate directory for Qualcomm firmware drivers and move existing sources in there. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Acked-by: Elliot Berman <quic_eberman@quicinc.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com> Tested-by: Andrew Halaney <ahalaney@redhat.com> # sc8280xp-lenovo-thinkpad-x13s Link: https://lore.kernel.org/r/20231017092732.19983-2-brgl@bgdev.pl Signed-off-by: Bjorn Andersson <andersson@kernel.org>
121 lines
3.0 KiB
C
121 lines
3.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
|
|
* Responsible for setting up and managing QSEECOM client devices.
|
|
*
|
|
* Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
|
|
*/
|
|
#include <linux/auxiliary_bus.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/firmware/qcom/qcom_qseecom.h>
|
|
#include <linux/firmware/qcom/qcom_scm.h>
|
|
|
|
struct qseecom_app_desc {
|
|
const char *app_name;
|
|
const char *dev_name;
|
|
};
|
|
|
|
static void qseecom_client_release(struct device *dev)
|
|
{
|
|
struct qseecom_client *client;
|
|
|
|
client = container_of(dev, struct qseecom_client, aux_dev.dev);
|
|
kfree(client);
|
|
}
|
|
|
|
static void qseecom_client_remove(void *data)
|
|
{
|
|
struct qseecom_client *client = data;
|
|
|
|
auxiliary_device_delete(&client->aux_dev);
|
|
auxiliary_device_uninit(&client->aux_dev);
|
|
}
|
|
|
|
static int qseecom_client_register(struct platform_device *qseecom_dev,
|
|
const struct qseecom_app_desc *desc)
|
|
{
|
|
struct qseecom_client *client;
|
|
u32 app_id;
|
|
int ret;
|
|
|
|
/* Try to find the app ID, skip device if not found */
|
|
ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
|
|
if (ret)
|
|
return ret == -ENOENT ? 0 : ret;
|
|
|
|
dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
|
|
|
|
/* Allocate and set-up the client device */
|
|
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
|
if (!client)
|
|
return -ENOMEM;
|
|
|
|
client->aux_dev.name = desc->dev_name;
|
|
client->aux_dev.dev.parent = &qseecom_dev->dev;
|
|
client->aux_dev.dev.release = qseecom_client_release;
|
|
client->app_id = app_id;
|
|
|
|
ret = auxiliary_device_init(&client->aux_dev);
|
|
if (ret) {
|
|
kfree(client);
|
|
return ret;
|
|
}
|
|
|
|
ret = auxiliary_device_add(&client->aux_dev);
|
|
if (ret) {
|
|
auxiliary_device_uninit(&client->aux_dev);
|
|
return ret;
|
|
}
|
|
|
|
ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* List of supported applications. One client device will be created per entry,
|
|
* assuming the app has already been loaded (usually by firmware bootloaders)
|
|
* and its ID can be queried successfully.
|
|
*/
|
|
static const struct qseecom_app_desc qcom_qseecom_apps[] = {
|
|
{ "qcom.tz.uefisecapp", "uefisecapp" },
|
|
};
|
|
|
|
static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
|
|
{
|
|
int ret;
|
|
int i;
|
|
|
|
/* Set up client devices for each base application */
|
|
for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
|
|
ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct platform_driver qcom_qseecom_driver = {
|
|
.driver = {
|
|
.name = "qcom_qseecom",
|
|
},
|
|
.probe = qcom_qseecom_probe,
|
|
};
|
|
|
|
static int __init qcom_qseecom_init(void)
|
|
{
|
|
return platform_driver_register(&qcom_qseecom_driver);
|
|
}
|
|
subsys_initcall(qcom_qseecom_init);
|
|
|
|
MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
|
|
MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
|
|
MODULE_LICENSE("GPL");
|