ipi.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
  4. * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. /*
  9. * Xilinx IPI agent registers access management
  10. */
  11. #include <errno.h>
  12. #include <string.h>
  13. #include <common/debug.h>
  14. #include <common/runtime_svc.h>
  15. #include <lib/bakery_lock.h>
  16. #include <lib/mmio.h>
  17. #include <ipi.h>
  18. #include <plat_private.h>
  19. /*********************************************************************
  20. * Macros definitions
  21. ********************************************************************/
  22. /* IPI registers offsets macros */
  23. #define IPI_TRIG_OFFSET 0x00U
  24. #define IPI_OBR_OFFSET 0x04U
  25. #define IPI_ISR_OFFSET 0x10U
  26. #define IPI_IMR_OFFSET 0x14U
  27. #define IPI_IER_OFFSET 0x18U
  28. #define IPI_IDR_OFFSET 0x1CU
  29. /* IPI register start offset */
  30. #define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base)
  31. /* IPI register bit mask */
  32. #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
  33. /* IPI configuration table */
  34. static const struct ipi_config *ipi_table;
  35. /* Total number of IPI */
  36. static uint32_t ipi_total;
  37. /**
  38. * ipi_config_table_init() - Initialize IPI configuration data.
  39. * @ipi_config_table: IPI configuration table.
  40. * @total_ipi: Total number of IPI available.
  41. *
  42. */
  43. void ipi_config_table_init(const struct ipi_config *ipi_config_table,
  44. uint32_t total_ipi)
  45. {
  46. ipi_table = ipi_config_table;
  47. ipi_total = total_ipi;
  48. }
  49. /**
  50. * is_ipi_mb_within_range() - verify if IPI mailbox is within range.
  51. * @local: local IPI ID.
  52. * @remote: remote IPI ID.
  53. *
  54. * Return: - 1 if within range, 0 if not.
  55. *
  56. */
  57. static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
  58. {
  59. int ret = 1;
  60. if ((remote >= ipi_total) || (local >= ipi_total)) {
  61. ret = 0;
  62. }
  63. return ret;
  64. }
  65. /**
  66. * ipi_mb_validate() - validate IPI mailbox access.
  67. * @local: local IPI ID.
  68. * @remote: remote IPI ID.
  69. * @is_secure: indicate if the requester is from secure software.
  70. *
  71. * Return: 0 success, negative value for errors.
  72. *
  73. */
  74. int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
  75. {
  76. int ret = 0;
  77. if (!is_ipi_mb_within_range(local, remote)) {
  78. ret = -EINVAL;
  79. } else if (IPI_IS_SECURE(local) && !is_secure) {
  80. ret = -EPERM;
  81. } else if (IPI_IS_SECURE(remote) && !is_secure) {
  82. ret = -EPERM;
  83. } else {
  84. /* To fix the misra 15.7 warning */
  85. }
  86. return ret;
  87. }
  88. /**
  89. * ipi_mb_open() - Open IPI mailbox.
  90. * @local: local IPI ID.
  91. * @remote: remote IPI ID.
  92. *
  93. */
  94. void ipi_mb_open(uint32_t local, uint32_t remote)
  95. {
  96. mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
  97. IPI_BIT_MASK(remote));
  98. mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
  99. IPI_BIT_MASK(remote));
  100. }
  101. /**
  102. * ipi_mb_release() - Open IPI mailbox.
  103. * @local: local IPI ID.
  104. * @remote: remote IPI ID.
  105. *
  106. */
  107. void ipi_mb_release(uint32_t local, uint32_t remote)
  108. {
  109. mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
  110. IPI_BIT_MASK(remote));
  111. }
  112. /**
  113. * ipi_mb_enquire_status() - Enquire IPI mailbox status.
  114. * @local: local IPI ID.
  115. * @remote: remote IPI ID.
  116. *
  117. * Return: 0 idle, positive value for pending sending or receiving,
  118. * negative value for errors.
  119. *
  120. */
  121. int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
  122. {
  123. int ret = 0U;
  124. uint32_t status;
  125. status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
  126. if ((status & IPI_BIT_MASK(remote)) != 0U) {
  127. ret |= IPI_MB_STATUS_SEND_PENDING;
  128. }
  129. status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
  130. if ((status & IPI_BIT_MASK(remote)) != 0U) {
  131. ret |= IPI_MB_STATUS_RECV_PENDING;
  132. }
  133. return ret;
  134. }
  135. /**
  136. * ipi_mb_notify() - Trigger IPI mailbox notification.
  137. * @local: local IPI ID.
  138. * @remote: remote IPI ID.
  139. * @is_blocking: if to trigger the notification in blocking mode or not.
  140. *
  141. * It sets the remote bit in the IPI agent trigger register.
  142. *
  143. */
  144. void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
  145. {
  146. uint32_t status;
  147. mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
  148. IPI_BIT_MASK(remote));
  149. if (is_blocking != 0U) {
  150. do {
  151. status = mmio_read_32(IPI_REG_BASE(local) +
  152. IPI_OBR_OFFSET);
  153. } while ((status & IPI_BIT_MASK(remote)) != 0U);
  154. }
  155. }
  156. /**
  157. * ipi_mb_ack() - Ack IPI mailbox notification from the other end.
  158. * @local: local IPI ID.
  159. * @remote: remote IPI ID.
  160. *
  161. * It will clear the remote bit in the isr register.
  162. *
  163. */
  164. void ipi_mb_ack(uint32_t local, uint32_t remote)
  165. {
  166. mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
  167. IPI_BIT_MASK(remote));
  168. }
  169. /**
  170. * ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt.
  171. * @local: local IPI ID.
  172. * @remote: remote IPI ID.
  173. *
  174. * It will mask the remote bit in the idr register.
  175. *
  176. */
  177. void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
  178. {
  179. mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
  180. IPI_BIT_MASK(remote));
  181. }
  182. /**
  183. * ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt.
  184. * @local: local IPI ID.
  185. * @remote: remote IPI ID.
  186. *
  187. * It will mask the remote bit in the idr register.
  188. *
  189. */
  190. void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
  191. {
  192. mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
  193. IPI_BIT_MASK(remote));
  194. }