reset-scmi.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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 <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "reset.scmi"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. struct scmi_reset
  16. {
  17. struct rt_reset_controller parent;
  18. struct rt_scmi_device *sdev;
  19. };
  20. #define raw_to_scmi_reset(raw) rt_container_of(raw, struct scmi_reset, parent)
  21. static rt_err_t scmi_reset_do(struct scmi_reset *srst, int domain,
  22. rt_uint32_t flags, rt_uint32_t state)
  23. {
  24. struct scmi_reset_in in =
  25. {
  26. .domain_id = rt_cpu_to_le32(domain),
  27. .flags = rt_cpu_to_le32(flags),
  28. .reset_state = rt_cpu_to_le32(state),
  29. };
  30. struct scmi_reset_out out;
  31. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_RESET_RESET, &in, &out);
  32. return rt_scmi_process_msg(srst->sdev, &msg);
  33. }
  34. static rt_err_t scmi_reset_reset(struct rt_reset_control *rstc)
  35. {
  36. struct scmi_reset *srst = raw_to_scmi_reset(rstc);
  37. return scmi_reset_do(srst, rstc->id, SCMI_RESET_FLAG_RESET, SCMI_ARCH_COLD_RESET);
  38. }
  39. static rt_err_t scmi_reset_assert(struct rt_reset_control *rstc)
  40. {
  41. struct scmi_reset *srst = raw_to_scmi_reset(rstc);
  42. return scmi_reset_do(srst, rstc->id, SCMI_RESET_FLAG_ASSERT, SCMI_ARCH_COLD_RESET);
  43. }
  44. static rt_err_t scmi_reset_deassert(struct rt_reset_control *rstc)
  45. {
  46. struct scmi_reset *srst = raw_to_scmi_reset(rstc);
  47. return scmi_reset_do(srst, rstc->id, 0, SCMI_ARCH_COLD_RESET);
  48. }
  49. static rt_err_t scmi_reset_ofw_parse(struct rt_reset_control *rstc,
  50. struct rt_ofw_cell_args *args)
  51. {
  52. rt_err_t err;
  53. struct scmi_reset *srst = raw_to_scmi_reset(rstc);
  54. struct scmi_reset_attr_in in =
  55. {
  56. .domain_id = rt_cpu_to_le32(rstc->id),
  57. };
  58. struct scmi_reset_attr_out out;
  59. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_RESET_DOMAIN_ATTRIBUTES, &in, &out);
  60. if ((err = rt_scmi_process_msg(srst->sdev, &msg)))
  61. {
  62. return err;
  63. }
  64. return rt_le32_to_cpu(out.status) == 0 ? RT_EOK : -RT_ERROR;
  65. }
  66. static const struct rt_reset_control_ops scmi_reset_ops =
  67. {
  68. .ofw_parse = scmi_reset_ofw_parse,
  69. .reset = scmi_reset_reset,
  70. .assert = scmi_reset_assert,
  71. .deassert = scmi_reset_deassert,
  72. };
  73. static rt_err_t scmi_reset_probe(struct rt_scmi_device *sdev)
  74. {
  75. rt_err_t err;
  76. struct rt_reset_controller *rstcer;
  77. struct scmi_reset *srst = rt_calloc(1, sizeof(*srst));
  78. if (!srst)
  79. {
  80. return -RT_ENOMEM;
  81. }
  82. rstcer = &srst->parent;
  83. rstcer->priv = srst;
  84. rstcer->ofw_node = sdev->parent.ofw_node;
  85. rstcer->ops = &scmi_reset_ops;
  86. if ((err = rt_reset_controller_register(&srst->parent)))
  87. {
  88. rt_free(srst);
  89. }
  90. return err;
  91. }
  92. static const struct rt_scmi_device_id scmi_reset_ids[] =
  93. {
  94. { SCMI_PROTOCOL_ID_RESET, "reset" },
  95. { /* sentinel */ },
  96. };
  97. static struct rt_scmi_driver scmi_reset_driver =
  98. {
  99. .name = "reset-scmi",
  100. .ids = scmi_reset_ids,
  101. .probe = scmi_reset_probe,
  102. };
  103. RT_SCMI_DRIVER_EXPORT(scmi_reset_driver);