syscon-poweroff.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-02-25 GuEe-GUI the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "reset.syscon.poweroff"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. static struct rt_syscon *syscon;
  16. static rt_uint32_t offset, value, mask;
  17. static void syscon_poweroff(void)
  18. {
  19. /* Issue the poweroff */
  20. rt_syscon_update_bits(syscon, offset, mask, value);
  21. rt_thread_mdelay(1000);
  22. LOG_E("Unable to poweroff system");
  23. }
  24. static rt_err_t syscon_poweroff_probe(struct rt_platform_device *pdev)
  25. {
  26. rt_err_t mask_err, value_err;
  27. struct rt_ofw_node *np = pdev->parent.ofw_node;
  28. syscon = rt_syscon_find_by_ofw_phandle(np, "regmap");
  29. if (!syscon)
  30. {
  31. return -RT_ERROR;
  32. }
  33. if (rt_ofw_prop_read_u32(np, "offset", &offset))
  34. {
  35. LOG_E("read '%s' fail", "offset");
  36. return -RT_EINVAL;
  37. }
  38. value_err = rt_ofw_prop_read_u32(np, "value", &value);
  39. mask_err = rt_ofw_prop_read_u32(np, "mask", &mask);
  40. if (value_err && mask_err)
  41. {
  42. LOG_E("read '%s' and '%s' fail", "value", "mask");
  43. return -RT_EINVAL;
  44. }
  45. if (value_err)
  46. {
  47. /* support old binding */
  48. value = mask;
  49. mask = 0xffffffff;
  50. }
  51. else if (mask_err)
  52. {
  53. /* support value without mask */
  54. mask = 0xffffffff;
  55. }
  56. if (rt_dm_machine_shutdown)
  57. {
  58. LOG_E("rt_dm_machine_shutdown have hook %p", rt_dm_machine_shutdown);
  59. return -RT_EBUSY;
  60. }
  61. rt_dm_machine_shutdown = syscon_poweroff;
  62. return RT_EOK;
  63. }
  64. static const struct rt_ofw_node_id syscon_poweroff_ofw_ids[] =
  65. {
  66. { .compatible = "syscon-poweroff" },
  67. { /* sentinel */ }
  68. };
  69. static struct rt_platform_driver syscon_poweroff_driver =
  70. {
  71. .name = "reset-syscon-poweroff",
  72. .ids = syscon_poweroff_ofw_ids,
  73. .probe = syscon_poweroff_probe,
  74. };
  75. static int syscon_poweroff_driver_register(void)
  76. {
  77. rt_platform_driver_register(&syscon_poweroff_driver);
  78. return 0;
  79. }
  80. INIT_SUBSYS_EXPORT(syscon_poweroff_driver_register);