agent.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include "agent.h"
  11. #define DBG_TAG "scmi.agent"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. rt_err_t rt_scmi_process_msg(struct rt_scmi_device *sdev, struct rt_scmi_msg *msg)
  15. {
  16. struct scmi_agent *agent;
  17. if (!sdev || !msg)
  18. {
  19. return -RT_EINVAL;
  20. }
  21. agent = sdev->agent;
  22. msg->sdev = sdev;
  23. return agent->ops->process_msg(agent, msg);
  24. }
  25. static const char * const _scmi_error_table[] =
  26. {
  27. [-SCMI_SUCCESS] = "SUCCESS",
  28. [-SCMI_ERR_SUPPORT] = "SUPPORT",
  29. [-SCMI_ERR_PARAMS] = "PARAMS",
  30. [-SCMI_ERR_ACCESS] = "ACCESS",
  31. [-SCMI_ERR_ENTRY] = "ENTRY",
  32. [-SCMI_ERR_RANGE] = "RANGE",
  33. [-SCMI_ERR_BUSY] = "BUSY",
  34. [-SCMI_ERR_COMMS] = "COMMS",
  35. [-SCMI_ERR_GENERIC] = "GENERIC",
  36. [-SCMI_ERR_HARDWARE] = "HARDWARE",
  37. [-SCMI_ERR_PROTOCOL] = "PROTOCOL",
  38. };
  39. const char *rt_scmi_strerror(rt_base_t err)
  40. {
  41. const char *str;
  42. err = err < 0 ? -err : err;
  43. if (err < RT_ARRAY_SIZE(_scmi_error_table))
  44. {
  45. str = _scmi_error_table[err];
  46. }
  47. else
  48. {
  49. str = "UNKNOWN";
  50. }
  51. return str;
  52. }
  53. static rt_err_t scmi_channels_setup(struct scmi_agent *agent,
  54. struct rt_platform_device *pdev)
  55. {
  56. struct rt_ofw_node *np = pdev->parent.ofw_node, *chn;
  57. rt_ofw_foreach_available_child_node(np, chn)
  58. {
  59. rt_uint32_t prot_id;
  60. struct rt_scmi_device *sdev;
  61. if (rt_ofw_prop_read_u32(chn, "reg", &prot_id))
  62. {
  63. continue;
  64. }
  65. sdev = rt_calloc(1, sizeof(*sdev));
  66. if (!sdev)
  67. {
  68. rt_ofw_node_put(chn);
  69. return -RT_ENOMEM;
  70. }
  71. sdev->parent.ofw_node = chn;
  72. sdev->protocol_id = prot_id;
  73. sdev->agent = agent;
  74. rt_scmi_device_register(sdev);
  75. }
  76. return RT_EOK;
  77. }
  78. static rt_err_t scmi_probe(struct rt_platform_device *pdev)
  79. {
  80. rt_err_t err;
  81. struct rt_scmi_device *base_sdev;
  82. struct scmi_agent *agent = rt_malloc(sizeof(*agent) + sizeof(*base_sdev));
  83. const struct scmi_agent_ops *agent_ops;
  84. if (!agent)
  85. {
  86. return -RT_ENOMEM;
  87. }
  88. agent_ops = pdev->id->data;
  89. agent->ops = agent_ops;
  90. if ((err = agent_ops->setup(agent, &pdev->parent)))
  91. {
  92. LOG_E("Setup interface %s error = %s", agent_ops->name, rt_strerror(err));
  93. goto _fail;
  94. }
  95. if ((err = scmi_channels_setup(agent, pdev)))
  96. {
  97. goto _fail;
  98. }
  99. base_sdev = (void *)&agent[1];
  100. rt_memset(base_sdev, 0, sizeof(*base_sdev));
  101. base_sdev->protocol_id = SCMI_PROTOCOL_ID_BASE;
  102. base_sdev->agent = agent;
  103. if ((err = rt_scmi_device_register(base_sdev)))
  104. {
  105. LOG_W("Base protocol register error = %s", rt_strerror(err));
  106. }
  107. return RT_EOK;
  108. _fail:
  109. rt_free(agent);
  110. return err;
  111. }
  112. extern struct rt_scmi_agent_ops scmi_agent_mailbox_ops;
  113. extern struct rt_scmi_agent_ops scmi_agent_smc_ops;
  114. extern struct rt_scmi_agent_ops scmi_agent_virtio_ops;
  115. static const struct rt_ofw_node_id scmi_ofw_ids[] =
  116. {
  117. #ifdef RT_FIRMWARE_ARM_SCMI_TRANSPORT_MAILBOX
  118. { .compatible = "arm,scmi", .data = &scmi_agent_mailbox_ops },
  119. #endif
  120. #ifdef RT_FIRMWARE_ARM_SCMI_TRANSPORT_SMC
  121. { .compatible = "arm,scmi-smc", .data = &scmi_agent_smc_ops },
  122. { .compatible = "arm,scmi-smc-param", .data = &scmi_agent_smc_ops },
  123. { .compatible = "qcom,scmi-smc", .data = &scmi_agent_smc_ops},
  124. #endif
  125. #ifdef RT_FIRMWARE_ARM_SCMI_TRANSPORT_VIRTIO
  126. { .compatible = "arm,scmi-virtio", .data = &scmi_agent_virtio_ops },
  127. #endif
  128. { /* sentinel */ }
  129. };
  130. static struct rt_platform_driver scmi_driver =
  131. {
  132. .name = "arm-scmi",
  133. .ids = scmi_ofw_ids,
  134. .probe = scmi_probe,
  135. };
  136. static int scmi_drv_register(void)
  137. {
  138. rt_platform_driver_register(&scmi_driver);
  139. return 0;
  140. }
  141. INIT_SUBSYS_EXPORT(scmi_drv_register);