sysreset-uclass.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <sysreset.h>
  8. #include <dm.h>
  9. #include <errno.h>
  10. #include <regmap.h>
  11. #include <dm/device-internal.h>
  12. #include <dm/lists.h>
  13. #include <dm/root.h>
  14. #include <linux/err.h>
  15. int sysreset_request(struct udevice *dev, enum sysreset_t type)
  16. {
  17. struct sysreset_ops *ops = sysreset_get_ops(dev);
  18. if (!ops->request)
  19. return -ENOSYS;
  20. return ops->request(dev, type);
  21. }
  22. int sysreset_get_status(struct udevice *dev, char *buf, int size)
  23. {
  24. struct sysreset_ops *ops = sysreset_get_ops(dev);
  25. if (!ops->get_status)
  26. return -ENOSYS;
  27. return ops->get_status(dev, buf, size);
  28. }
  29. int sysreset_walk(enum sysreset_t type)
  30. {
  31. struct udevice *dev;
  32. int ret = -ENOSYS;
  33. while (ret != -EINPROGRESS && type < SYSRESET_COUNT) {
  34. for (uclass_first_device(UCLASS_SYSRESET, &dev);
  35. dev;
  36. uclass_next_device(&dev)) {
  37. ret = sysreset_request(dev, type);
  38. if (ret == -EINPROGRESS)
  39. break;
  40. }
  41. type++;
  42. }
  43. return ret;
  44. }
  45. void sysreset_walk_halt(enum sysreset_t type)
  46. {
  47. int ret;
  48. ret = sysreset_walk(type);
  49. /* Wait for the reset to take effect */
  50. if (ret == -EINPROGRESS)
  51. mdelay(100);
  52. /* Still no reset? Give up */
  53. debug("System reset not supported on this platform\n");
  54. hang();
  55. }
  56. /**
  57. * reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
  58. */
  59. void reset_cpu(ulong addr)
  60. {
  61. sysreset_walk_halt(SYSRESET_WARM);
  62. }
  63. int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  64. {
  65. printf("resetting ...\n");
  66. sysreset_walk_halt(SYSRESET_COLD);
  67. return 0;
  68. }
  69. static int sysreset_post_bind(struct udevice *dev)
  70. {
  71. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  72. struct sysreset_ops *ops = sysreset_get_ops(dev);
  73. static int reloc_done;
  74. if (!reloc_done) {
  75. if (ops->request)
  76. ops->request += gd->reloc_off;
  77. reloc_done++;
  78. }
  79. #endif
  80. return 0;
  81. }
  82. UCLASS_DRIVER(sysreset) = {
  83. .id = UCLASS_SYSRESET,
  84. .name = "sysreset",
  85. .post_bind = sysreset_post_bind,
  86. };