qcom_qseecom.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. #include <linux/firmware/qcom/qcom_qseecom.h>
  14. #include <linux/firmware/qcom/qcom_scm.h>
  15. struct qseecom_app_desc {
  16. const char *app_name;
  17. const char *dev_name;
  18. };
  19. static void qseecom_client_release(struct device *dev)
  20. {
  21. struct qseecom_client *client;
  22. client = container_of(dev, struct qseecom_client, aux_dev.dev);
  23. kfree(client);
  24. }
  25. static void qseecom_client_remove(void *data)
  26. {
  27. struct qseecom_client *client = data;
  28. auxiliary_device_delete(&client->aux_dev);
  29. auxiliary_device_uninit(&client->aux_dev);
  30. }
  31. static int qseecom_client_register(struct platform_device *qseecom_dev,
  32. const struct qseecom_app_desc *desc)
  33. {
  34. struct qseecom_client *client;
  35. u32 app_id;
  36. int ret;
  37. /* Try to find the app ID, skip device if not found */
  38. ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
  39. if (ret)
  40. return ret == -ENOENT ? 0 : ret;
  41. dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
  42. /* Allocate and set-up the client device */
  43. client = kzalloc(sizeof(*client), GFP_KERNEL);
  44. if (!client)
  45. return -ENOMEM;
  46. client->aux_dev.name = desc->dev_name;
  47. client->aux_dev.dev.parent = &qseecom_dev->dev;
  48. client->aux_dev.dev.release = qseecom_client_release;
  49. client->app_id = app_id;
  50. ret = auxiliary_device_init(&client->aux_dev);
  51. if (ret) {
  52. kfree(client);
  53. return ret;
  54. }
  55. ret = auxiliary_device_add(&client->aux_dev);
  56. if (ret) {
  57. auxiliary_device_uninit(&client->aux_dev);
  58. return ret;
  59. }
  60. ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
  61. if (ret)
  62. return ret;
  63. return 0;
  64. }
  65. /*
  66. * List of supported applications. One client device will be created per entry,
  67. * assuming the app has already been loaded (usually by firmware bootloaders)
  68. * and its ID can be queried successfully.
  69. */
  70. static const struct qseecom_app_desc qcom_qseecom_apps[] = {
  71. { "qcom.tz.uefisecapp", "uefisecapp" },
  72. };
  73. static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
  74. {
  75. int ret;
  76. int i;
  77. /* Set up client devices for each base application */
  78. for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
  79. ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
  80. if (ret)
  81. return ret;
  82. }
  83. return 0;
  84. }
  85. static struct platform_driver qcom_qseecom_driver = {
  86. .driver = {
  87. .name = "qcom_qseecom",
  88. },
  89. .probe = qcom_qseecom_probe,
  90. };
  91. static int __init qcom_qseecom_init(void)
  92. {
  93. return platform_driver_register(&qcom_qseecom_driver);
  94. }
  95. subsys_initcall(qcom_qseecom_init);
  96. MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  97. MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
  98. MODULE_LICENSE("GPL");