gpio_wdt.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <dm.h>
  3. #include <dm/device_compat.h>
  4. #include <wdt.h>
  5. #include <asm/gpio.h>
  6. #include <linux/delay.h>
  7. enum {
  8. HW_ALGO_TOGGLE,
  9. HW_ALGO_LEVEL,
  10. };
  11. struct gpio_wdt_priv {
  12. struct gpio_desc gpio;
  13. unsigned int hw_algo;
  14. bool always_running;
  15. int state;
  16. };
  17. static int gpio_wdt_reset(struct udevice *dev)
  18. {
  19. struct gpio_wdt_priv *priv = dev_get_priv(dev);
  20. switch (priv->hw_algo) {
  21. case HW_ALGO_TOGGLE:
  22. /* Toggle output pin */
  23. priv->state = !priv->state;
  24. dm_gpio_set_value(&priv->gpio, priv->state);
  25. break;
  26. case HW_ALGO_LEVEL:
  27. /* Pulse */
  28. dm_gpio_set_value(&priv->gpio, 1);
  29. __udelay(1);
  30. dm_gpio_set_value(&priv->gpio, 0);
  31. break;
  32. }
  33. return 0;
  34. }
  35. static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
  36. {
  37. struct gpio_wdt_priv *priv = dev_get_priv(dev);
  38. if (priv->always_running)
  39. return 0;
  40. return -ENOSYS;
  41. }
  42. static int dm_probe(struct udevice *dev)
  43. {
  44. struct gpio_wdt_priv *priv = dev_get_priv(dev);
  45. int ret;
  46. const char *algo = dev_read_string(dev, "hw_algo");
  47. if (!algo)
  48. return -EINVAL;
  49. if (!strcmp(algo, "toggle"))
  50. priv->hw_algo = HW_ALGO_TOGGLE;
  51. else if (!strcmp(algo, "level"))
  52. priv->hw_algo = HW_ALGO_LEVEL;
  53. else
  54. return -EINVAL;
  55. priv->always_running = dev_read_bool(dev, "always-running");
  56. ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
  57. if (ret < 0) {
  58. dev_err(dev, "Request for wdt gpio failed: %d\n", ret);
  59. return ret;
  60. }
  61. if (priv->always_running)
  62. ret = gpio_wdt_reset(dev);
  63. return ret;
  64. }
  65. static const struct wdt_ops gpio_wdt_ops = {
  66. .start = gpio_wdt_start,
  67. .reset = gpio_wdt_reset,
  68. };
  69. static const struct udevice_id gpio_wdt_ids[] = {
  70. { .compatible = "linux,wdt-gpio" },
  71. {}
  72. };
  73. U_BOOT_DRIVER(wdt_gpio) = {
  74. .name = "wdt_gpio",
  75. .id = UCLASS_WDT,
  76. .of_match = gpio_wdt_ids,
  77. .ops = &gpio_wdt_ops,
  78. .probe = dm_probe,
  79. .priv_auto = sizeof(struct gpio_wdt_priv),
  80. };