shmem.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-26 GuEe-GUI first version
  9. */
  10. #define DBG_TAG "scmi.shmem"
  11. #define DBG_LVL DBG_INFO
  12. #include <rtdbg.h>
  13. #include "shmem.h"
  14. struct scmi_shared_mem
  15. {
  16. rt_le32_t reserved;
  17. rt_le32_t channel_status;
  18. #define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR rt_cpu_to_le32(RT_BIT(1))
  19. #define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE rt_cpu_to_le32(RT_BIT(0))
  20. rt_le32_t reserved1[2];
  21. rt_le32_t flags;
  22. #define SCMI_SHMEM_FLAG_INTR_ENABLED rt_cpu_to_le32(RT_BIT(0))
  23. rt_le32_t length;
  24. rt_le32_t msg_header;
  25. rt_uint8_t msg_payload[];
  26. };
  27. rt_err_t scmi_shmem_msg_write(struct scmi_shared_mem *shmem,
  28. struct rt_scmi_msg *msg)
  29. {
  30. if (!shmem || !msg)
  31. {
  32. return -RT_EINVAL;
  33. }
  34. if ((!msg->in_msg && msg->in_msg_size) || (!msg->out_msg && msg->out_msg_size))
  35. {
  36. return -RT_EINVAL;
  37. }
  38. if (!(shmem->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE))
  39. {
  40. LOG_E("Channel busy");
  41. return -RT_EBUSY;
  42. }
  43. /* Load message in shared memory */
  44. shmem->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
  45. shmem->length = rt_cpu_to_le32(msg->in_msg_size + sizeof(shmem->msg_header));
  46. shmem->msg_header = rt_cpu_to_le32(scmi_header(
  47. msg->message_id, 0, msg->sdev->protocol_id, 0));
  48. if (msg->in_msg)
  49. {
  50. rt_memcpy(shmem->msg_payload, msg->in_msg, msg->in_msg_size);
  51. }
  52. return RT_EOK;
  53. }
  54. rt_err_t scmi_shmem_msg_read(struct scmi_shared_mem *shmem, struct rt_scmi_msg *msg)
  55. {
  56. rt_size_t length;
  57. if (!shmem || !msg)
  58. {
  59. return -RT_EINVAL;
  60. }
  61. if (!(shmem->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE))
  62. {
  63. LOG_E("Channel unexpectedly busy");
  64. return -RT_EBUSY;
  65. }
  66. if (shmem->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR)
  67. {
  68. LOG_E("Channel error reported, reset channel");
  69. return -RT_EIO;
  70. }
  71. length = rt_le32_to_cpu(shmem->length);
  72. if (length > msg->out_msg_size + sizeof(shmem->msg_header))
  73. {
  74. LOG_E("Buffer < %u too small", length);
  75. return -RT_EINVAL;
  76. }
  77. msg->out_msg_size = length - sizeof(shmem->msg_header);
  78. rt_memcpy(msg->out_msg, shmem->msg_payload, msg->out_msg_size);
  79. return RT_EOK;
  80. }
  81. void scmi_shmem_clear_channel(struct scmi_shared_mem *shmem)
  82. {
  83. if (shmem)
  84. {
  85. shmem->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR;
  86. }
  87. }