poweroff_gpio.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Toggles a GPIO pin to power down a device
  4. *
  5. * Created using the Linux driver as reference, which
  6. * has been written by:
  7. *
  8. * Jamie Lentin <jm@lentin.co.uk>
  9. * Andrew Lunn <andrew@lunn.ch>
  10. *
  11. * Copyright (C) 2012 Jamie Lentin
  12. */
  13. #include <common.h>
  14. #include <dm.h>
  15. #include <errno.h>
  16. #include <log.h>
  17. #include <sysreset.h>
  18. #include <asm/gpio.h>
  19. #include <linux/delay.h>
  20. struct poweroff_gpio_info {
  21. struct gpio_desc gpio;
  22. u32 active_delay_ms;
  23. u32 inactive_delay_ms;
  24. u32 timeout_ms;
  25. };
  26. static int poweroff_gpio_request(struct udevice *dev, enum sysreset_t type)
  27. {
  28. struct poweroff_gpio_info *priv = dev_get_priv(dev);
  29. int r;
  30. if (type != SYSRESET_POWER_OFF)
  31. return -ENOSYS;
  32. debug("GPIO poweroff\n");
  33. /* drive it active, also inactive->active edge */
  34. r = dm_gpio_set_value(&priv->gpio, 1);
  35. if (r < 0)
  36. return r;
  37. mdelay(priv->active_delay_ms);
  38. /* drive inactive, also active->inactive edge */
  39. r = dm_gpio_set_value(&priv->gpio, 0);
  40. if (r < 0)
  41. return r;
  42. mdelay(priv->inactive_delay_ms);
  43. /* drive it active, also inactive->active edge */
  44. r = dm_gpio_set_value(&priv->gpio, 1);
  45. if (r < 0)
  46. return r;
  47. /* give it some time */
  48. mdelay(priv->timeout_ms);
  49. return -EINPROGRESS;
  50. }
  51. static int poweroff_gpio_probe(struct udevice *dev)
  52. {
  53. struct poweroff_gpio_info *priv = dev_get_priv(dev);
  54. int flags;
  55. flags = dev_read_bool(dev, "input") ? GPIOD_IS_IN : GPIOD_IS_OUT;
  56. priv->active_delay_ms = dev_read_u32_default(dev, "active-delay-ms", 100);
  57. priv->inactive_delay_ms = dev_read_u32_default(dev, "inactive-delay-ms", 100);
  58. priv->timeout_ms = dev_read_u32_default(dev, "timeout-ms", 3000);
  59. return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags);
  60. }
  61. static struct sysreset_ops poweroff_gpio_ops = {
  62. .request = poweroff_gpio_request,
  63. };
  64. static const struct udevice_id poweroff_gpio_ids[] = {
  65. { .compatible = "gpio-poweroff", },
  66. {},
  67. };
  68. U_BOOT_DRIVER(poweroff_gpio) = {
  69. .name = "poweroff-gpio",
  70. .id = UCLASS_SYSRESET,
  71. .ops = &poweroff_gpio_ops,
  72. .probe = poweroff_gpio_probe,
  73. .priv_auto = sizeof(struct poweroff_gpio_info),
  74. .of_match = poweroff_gpio_ids,
  75. };