mei_pxp.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright © 2020 - 2021 Intel Corporation
  4. */
  5. /**
  6. * DOC: MEI_PXP Client Driver
  7. *
  8. * The mei_pxp driver acts as a translation layer between PXP
  9. * protocol implementer (I915) and ME FW by translating PXP
  10. * negotiation messages to ME FW command payloads and vice versa.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/slab.h>
  14. #include <linux/uuid.h>
  15. #include <linux/mei_cl_bus.h>
  16. #include <linux/component.h>
  17. #include <drm/drm_connector.h>
  18. #include <drm/i915_component.h>
  19. #include <drm/i915_pxp_tee_interface.h>
  20. #include "mei_pxp.h"
  21. /**
  22. * mei_pxp_send_message() - Sends a PXP message to ME FW.
  23. * @dev: device corresponding to the mei_cl_device
  24. * @message: a message buffer to send
  25. * @size: size of the message
  26. * Return: 0 on Success, <0 on Failure
  27. */
  28. static int
  29. mei_pxp_send_message(struct device *dev, const void *message, size_t size)
  30. {
  31. struct mei_cl_device *cldev;
  32. ssize_t byte;
  33. if (!dev || !message)
  34. return -EINVAL;
  35. cldev = to_mei_cl_device(dev);
  36. /* temporary drop const qualifier till the API is fixed */
  37. byte = mei_cldev_send(cldev, (u8 *)message, size);
  38. if (byte < 0) {
  39. dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte);
  40. return byte;
  41. }
  42. return 0;
  43. }
  44. /**
  45. * mei_pxp_receive_message() - Receives a PXP message from ME FW.
  46. * @dev: device corresponding to the mei_cl_device
  47. * @buffer: a message buffer to contain the received message
  48. * @size: size of the buffer
  49. * Return: bytes sent on Success, <0 on Failure
  50. */
  51. static int
  52. mei_pxp_receive_message(struct device *dev, void *buffer, size_t size)
  53. {
  54. struct mei_cl_device *cldev;
  55. ssize_t byte;
  56. if (!dev || !buffer)
  57. return -EINVAL;
  58. cldev = to_mei_cl_device(dev);
  59. byte = mei_cldev_recv(cldev, buffer, size);
  60. if (byte < 0) {
  61. dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
  62. return byte;
  63. }
  64. return byte;
  65. }
  66. static const struct i915_pxp_component_ops mei_pxp_ops = {
  67. .owner = THIS_MODULE,
  68. .send = mei_pxp_send_message,
  69. .recv = mei_pxp_receive_message,
  70. };
  71. static int mei_component_master_bind(struct device *dev)
  72. {
  73. struct mei_cl_device *cldev = to_mei_cl_device(dev);
  74. struct i915_pxp_component *comp_master = mei_cldev_get_drvdata(cldev);
  75. int ret;
  76. comp_master->ops = &mei_pxp_ops;
  77. comp_master->tee_dev = dev;
  78. ret = component_bind_all(dev, comp_master);
  79. if (ret < 0)
  80. return ret;
  81. return 0;
  82. }
  83. static void mei_component_master_unbind(struct device *dev)
  84. {
  85. struct mei_cl_device *cldev = to_mei_cl_device(dev);
  86. struct i915_pxp_component *comp_master = mei_cldev_get_drvdata(cldev);
  87. component_unbind_all(dev, comp_master);
  88. }
  89. static const struct component_master_ops mei_component_master_ops = {
  90. .bind = mei_component_master_bind,
  91. .unbind = mei_component_master_unbind,
  92. };
  93. /**
  94. * mei_pxp_component_match - compare function for matching mei pxp.
  95. *
  96. * The function checks if the driver is i915, the subcomponent is PXP
  97. * and the grand parent of pxp and the parent of i915 are the same
  98. * PCH device.
  99. *
  100. * @dev: master device
  101. * @subcomponent: subcomponent to match (I915_COMPONENT_PXP)
  102. * @data: compare data (mei pxp device)
  103. *
  104. * Return:
  105. * * 1 - if components match
  106. * * 0 - otherwise
  107. */
  108. static int mei_pxp_component_match(struct device *dev, int subcomponent,
  109. void *data)
  110. {
  111. struct device *base = data;
  112. if (!dev->driver || strcmp(dev->driver->name, "i915") ||
  113. subcomponent != I915_COMPONENT_PXP)
  114. return 0;
  115. base = base->parent;
  116. if (!base)
  117. return 0;
  118. base = base->parent;
  119. dev = dev->parent;
  120. return (base && dev && dev == base);
  121. }
  122. static int mei_pxp_probe(struct mei_cl_device *cldev,
  123. const struct mei_cl_device_id *id)
  124. {
  125. struct i915_pxp_component *comp_master;
  126. struct component_match *master_match;
  127. int ret;
  128. ret = mei_cldev_enable(cldev);
  129. if (ret < 0) {
  130. dev_err(&cldev->dev, "mei_cldev_enable Failed. %d\n", ret);
  131. goto enable_err_exit;
  132. }
  133. comp_master = kzalloc(sizeof(*comp_master), GFP_KERNEL);
  134. if (!comp_master) {
  135. ret = -ENOMEM;
  136. goto err_exit;
  137. }
  138. master_match = NULL;
  139. component_match_add_typed(&cldev->dev, &master_match,
  140. mei_pxp_component_match, &cldev->dev);
  141. if (IS_ERR_OR_NULL(master_match)) {
  142. ret = -ENOMEM;
  143. goto err_exit;
  144. }
  145. mei_cldev_set_drvdata(cldev, comp_master);
  146. ret = component_master_add_with_match(&cldev->dev,
  147. &mei_component_master_ops,
  148. master_match);
  149. if (ret < 0) {
  150. dev_err(&cldev->dev, "Master comp add failed %d\n", ret);
  151. goto err_exit;
  152. }
  153. return 0;
  154. err_exit:
  155. mei_cldev_set_drvdata(cldev, NULL);
  156. kfree(comp_master);
  157. mei_cldev_disable(cldev);
  158. enable_err_exit:
  159. return ret;
  160. }
  161. static void mei_pxp_remove(struct mei_cl_device *cldev)
  162. {
  163. struct i915_pxp_component *comp_master = mei_cldev_get_drvdata(cldev);
  164. int ret;
  165. component_master_del(&cldev->dev, &mei_component_master_ops);
  166. kfree(comp_master);
  167. mei_cldev_set_drvdata(cldev, NULL);
  168. ret = mei_cldev_disable(cldev);
  169. if (ret)
  170. dev_warn(&cldev->dev, "mei_cldev_disable() failed\n");
  171. }
  172. /* fbf6fcf1-96cf-4e2e-a6a6-1bab8cbe36b1 : PAVP GUID*/
  173. #define MEI_GUID_PXP UUID_LE(0xfbf6fcf1, 0x96cf, 0x4e2e, 0xA6, \
  174. 0xa6, 0x1b, 0xab, 0x8c, 0xbe, 0x36, 0xb1)
  175. static struct mei_cl_device_id mei_pxp_tbl[] = {
  176. { .uuid = MEI_GUID_PXP, .version = MEI_CL_VERSION_ANY },
  177. { }
  178. };
  179. MODULE_DEVICE_TABLE(mei, mei_pxp_tbl);
  180. static struct mei_cl_driver mei_pxp_driver = {
  181. .id_table = mei_pxp_tbl,
  182. .name = KBUILD_MODNAME,
  183. .probe = mei_pxp_probe,
  184. .remove = mei_pxp_remove,
  185. };
  186. module_mei_cl_driver(mei_pxp_driver);
  187. MODULE_AUTHOR("Intel Corporation");
  188. MODULE_LICENSE("GPL");
  189. MODULE_DESCRIPTION("MEI PXP");