platform-access.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * AMD Platform Security Processor (PSP) Platform Access interface
  4. *
  5. * Copyright (C) 2023 Advanced Micro Devices, Inc.
  6. *
  7. * Author: Mario Limonciello <mario.limonciello@amd.com>
  8. *
  9. * Some of this code is adapted from drivers/i2c/busses/i2c-designware-amdpsp.c
  10. * developed by Jan Dabros <jsd@semihalf.com> and Copyright (C) 2022 Google Inc.
  11. *
  12. */
  13. #include <linux/bitfield.h>
  14. #include <linux/errno.h>
  15. #include <linux/iopoll.h>
  16. #include <linux/mutex.h>
  17. #include "platform-access.h"
  18. #define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC)
  19. #define DOORBELL_CMDRESP_STS GENMASK(7, 0)
  20. /* Recovery field should be equal 0 to start sending commands */
  21. static int check_recovery(u32 __iomem *cmd)
  22. {
  23. return FIELD_GET(PSP_CMDRESP_RECOVERY, ioread32(cmd));
  24. }
  25. static int wait_cmd(u32 __iomem *cmd)
  26. {
  27. u32 tmp, expected;
  28. /* Expect mbox_cmd to be cleared and ready bit to be set by PSP */
  29. expected = FIELD_PREP(PSP_CMDRESP_RESP, 1);
  30. /*
  31. * Check for readiness of PSP mailbox in a tight loop in order to
  32. * process further as soon as command was consumed.
  33. */
  34. return readl_poll_timeout(cmd, tmp, (tmp & expected), 0,
  35. PSP_CMD_TIMEOUT_US);
  36. }
  37. int psp_check_platform_access_status(void)
  38. {
  39. struct psp_device *psp = psp_get_master_device();
  40. if (!psp || !psp->platform_access_data)
  41. return -ENODEV;
  42. return 0;
  43. }
  44. EXPORT_SYMBOL(psp_check_platform_access_status);
  45. int psp_send_platform_access_msg(enum psp_platform_access_msg msg,
  46. struct psp_request *req)
  47. {
  48. struct psp_device *psp = psp_get_master_device();
  49. u32 __iomem *cmd, *lo, *hi;
  50. struct psp_platform_access_device *pa_dev;
  51. phys_addr_t req_addr;
  52. u32 cmd_reg;
  53. int ret;
  54. if (!psp || !psp->platform_access_data)
  55. return -ENODEV;
  56. pa_dev = psp->platform_access_data;
  57. if (!pa_dev->vdata->cmdresp_reg || !pa_dev->vdata->cmdbuff_addr_lo_reg ||
  58. !pa_dev->vdata->cmdbuff_addr_hi_reg)
  59. return -ENODEV;
  60. cmd = psp->io_regs + pa_dev->vdata->cmdresp_reg;
  61. lo = psp->io_regs + pa_dev->vdata->cmdbuff_addr_lo_reg;
  62. hi = psp->io_regs + pa_dev->vdata->cmdbuff_addr_hi_reg;
  63. mutex_lock(&pa_dev->mailbox_mutex);
  64. if (check_recovery(cmd)) {
  65. dev_dbg(psp->dev, "platform mailbox is in recovery\n");
  66. ret = -EBUSY;
  67. goto unlock;
  68. }
  69. if (wait_cmd(cmd)) {
  70. dev_dbg(psp->dev, "platform mailbox is not done processing command\n");
  71. ret = -EBUSY;
  72. goto unlock;
  73. }
  74. /*
  75. * Fill mailbox with address of command-response buffer, which will be
  76. * used for sending i2c requests as well as reading status returned by
  77. * PSP. Use physical address of buffer, since PSP will map this region.
  78. */
  79. req_addr = __psp_pa(req);
  80. iowrite32(lower_32_bits(req_addr), lo);
  81. iowrite32(upper_32_bits(req_addr), hi);
  82. print_hex_dump_debug("->psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
  83. req->header.payload_size, false);
  84. /* Write command register to trigger processing */
  85. cmd_reg = FIELD_PREP(PSP_CMDRESP_CMD, msg);
  86. iowrite32(cmd_reg, cmd);
  87. if (wait_cmd(cmd)) {
  88. ret = -ETIMEDOUT;
  89. goto unlock;
  90. }
  91. /* Ensure it was triggered by this driver */
  92. if (ioread32(lo) != lower_32_bits(req_addr) ||
  93. ioread32(hi) != upper_32_bits(req_addr)) {
  94. ret = -EBUSY;
  95. goto unlock;
  96. }
  97. /*
  98. * Read status from PSP. If status is non-zero, it indicates an error
  99. * occurred during "processing" of the command.
  100. * If status is zero, it indicates the command was "processed"
  101. * successfully, but the result of the command is in the payload.
  102. * Return both cases to the caller as -EIO to investigate.
  103. */
  104. cmd_reg = ioread32(cmd);
  105. if (FIELD_GET(PSP_CMDRESP_STS, cmd_reg))
  106. req->header.status = FIELD_GET(PSP_CMDRESP_STS, cmd_reg);
  107. if (req->header.status) {
  108. ret = -EIO;
  109. goto unlock;
  110. }
  111. print_hex_dump_debug("<-psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
  112. req->header.payload_size, false);
  113. ret = 0;
  114. unlock:
  115. mutex_unlock(&pa_dev->mailbox_mutex);
  116. return ret;
  117. }
  118. EXPORT_SYMBOL_GPL(psp_send_platform_access_msg);
  119. int psp_ring_platform_doorbell(int msg, u32 *result)
  120. {
  121. struct psp_device *psp = psp_get_master_device();
  122. struct psp_platform_access_device *pa_dev;
  123. u32 __iomem *button, *cmd;
  124. int ret, val;
  125. if (!psp || !psp->platform_access_data)
  126. return -ENODEV;
  127. pa_dev = psp->platform_access_data;
  128. button = psp->io_regs + pa_dev->vdata->doorbell_button_reg;
  129. cmd = psp->io_regs + pa_dev->vdata->doorbell_cmd_reg;
  130. mutex_lock(&pa_dev->doorbell_mutex);
  131. if (wait_cmd(cmd)) {
  132. dev_err(psp->dev, "doorbell command not done processing\n");
  133. ret = -EBUSY;
  134. goto unlock;
  135. }
  136. iowrite32(FIELD_PREP(DOORBELL_CMDRESP_STS, msg), cmd);
  137. iowrite32(PSP_DRBL_RING, button);
  138. if (wait_cmd(cmd)) {
  139. ret = -ETIMEDOUT;
  140. goto unlock;
  141. }
  142. val = FIELD_GET(DOORBELL_CMDRESP_STS, ioread32(cmd));
  143. if (val) {
  144. if (result)
  145. *result = val;
  146. ret = -EIO;
  147. goto unlock;
  148. }
  149. ret = 0;
  150. unlock:
  151. mutex_unlock(&pa_dev->doorbell_mutex);
  152. return ret;
  153. }
  154. EXPORT_SYMBOL_GPL(psp_ring_platform_doorbell);
  155. void platform_access_dev_destroy(struct psp_device *psp)
  156. {
  157. struct psp_platform_access_device *pa_dev = psp->platform_access_data;
  158. if (!pa_dev)
  159. return;
  160. mutex_destroy(&pa_dev->mailbox_mutex);
  161. mutex_destroy(&pa_dev->doorbell_mutex);
  162. psp->platform_access_data = NULL;
  163. }
  164. int platform_access_dev_init(struct psp_device *psp)
  165. {
  166. struct device *dev = psp->dev;
  167. struct psp_platform_access_device *pa_dev;
  168. pa_dev = devm_kzalloc(dev, sizeof(*pa_dev), GFP_KERNEL);
  169. if (!pa_dev)
  170. return -ENOMEM;
  171. psp->platform_access_data = pa_dev;
  172. pa_dev->psp = psp;
  173. pa_dev->dev = dev;
  174. pa_dev->vdata = (struct platform_access_vdata *)psp->vdata->platform_access;
  175. mutex_init(&pa_dev->mailbox_mutex);
  176. mutex_init(&pa_dev->doorbell_mutex);
  177. dev_dbg(dev, "platform access enabled\n");
  178. return 0;
  179. }